Author |
Message |
Ron Alexande #1 / 41
|
 SCANF() NEWBIE
I was hoping that someone could tell me why I can't scan in a number and then multiply it times 100 without resulting in a number that's off by one, but only in some cases??? Thanks, Ron #include <stdio.h> void main(void) { int pennies, nickels, dimes, quarters; int dollar, amnt100; float amnt; printf("Enter dollar amount in decimal format: "); scanf("%f", &amnt); amnt100 = amnt * 100; Quote: }
Input of 67.67 results in an assignment of 6766 to variable amnt100. Some other values: Input amnt100 67.60 **6759** 67.61 6761 67.62 6762 67.63 **6762** 67.64 **6763** 67.65 6765 67.66 6766 67.67 **6766** 67.68 6768 67.69 6769 --
|
Wed, 07 Mar 2001 03:00:00 GMT |
|
 |
Gene Wirchen #2 / 41
|
 SCANF() NEWBIE
Quote:
>I was hoping that someone could tell me why I can't scan in a number >and then multiply it times 100 without resulting in a number that's >off by one, but only in some cases???
Sure. It has to do with two things. 1) float does not represent some numbers precisely. 2) A conversion to int truncates away the decimal places. (It doesn't round.) Quote: >Thanks, >Ron >#include <stdio.h> >void main(void)
"I'm sorry, but I'm going to have to shoot you." -Monty python (quote or paraphrase?) Per the Standard, main() is required to return int unless you have a freestanding installation. If you don't know what that is, you don't have one (almost certainly). A freestanding installation would be as in an embedded control system. Quote: >{ > int pennies, nickels, dimes, quarters; > int dollar, amnt100; > float amnt; > printf("Enter dollar amount in decimal format: "); > scanf("%f", &amnt); > amnt100 = amnt * 100; >} > Input of 67.67 results in an assignment of 6766 to variable amnt100.
More precisely, on your system, input of "67.67" results in an assignment of just under 67.67 to the float. This multiplied by 100 is just under 6767 and the conversion to int truncates the decimal places. Voila 6766. My kludge would be amnt100=amnt*100+.005; which will effectively result in rounding. Others more knowledgeable may have better ways. Quote: > Some other values: > Input amnt100 > 67.60 **6759** > 67.61 6761 > 67.62 6762 > 67.63 **6762** > 67.64 **6763** > 67.65 6765 > 67.66 6766 > 67.67 **6766** > 67.68 6768 > 67.69 6769
The same sort of logic applies to your other cases. Sincerely, Gene Wirchenko Computerese Irregular Verb Conjugation: I have preferences. You have biases. He/She has prejudices. --
|
Fri, 09 Mar 2001 03:00:00 GMT |
|
 |
Francis Glassboro #3 / 41
|
 SCANF() NEWBIE
Quote: >I was hoping that someone could tell me why I can't scan in a number >and then multiply it times 100 without resulting in a number that's >off by one, but only in some cases??? >Thanks, >Ron >#include <stdio.h> >void main(void)
^^^^ ugh! should be int Quote: >{ > int pennies, nickels, dimes, quarters; > int dollar, amnt100; > float amnt; > printf("Enter dollar amount in decimal format: "); > scanf("%f", &amnt); > amnt100 = amnt * 100; >}
Because of the limitations of the internal (usually binary) representation of floats and its subsequent conversion to int. It has little to do with the fact that you scanned in the values. This is one of numerous reasons why you should not use floating point types for financial calculations. Francis Glassborow Chair of Association of C & C++ Users 64 Southfield Rd Oxford OX4 1PA +44(0)1865 246490 All opinions are mine and do not represent those of any organisation --
|
Fri, 09 Mar 2001 03:00:00 GMT |
|
 |
Herb Illfelde #4 / 41
|
 SCANF() NEWBIE
Quote:
> I was hoping that someone could tell me why I can't scan in a number > and then multiply it times 100 without resulting in a number that's > off by one, but only in some cases??? > Thanks, > Ron > #include <stdio.h> > void main(void) > { > int pennies, nickels, dimes, quarters; > int dollar, amnt100; > float amnt; > printf("Enter dollar amount in decimal format: "); > scanf("%f", &amnt); > amnt100 = amnt * 100; > } > Input of 67.67 results in an assignment of 6766 to variable amnt100. > Some other values: > Input amnt100 > 67.60 **6759** > 67.61 6761 > 67.62 6762 > 67.63 **6762** > 67.64 **6763** > 67.65 6765 > 67.66 6766 > 67.67 **6766** > 67.68 6768 > 67.69 6769 > --
You are caught by the difference between decimal & binary. In decimal, rhink of the number 1/3 which is written as 0.333... Now, computers can only store a limited number of digits, in this example, like 0.333333333 Multiple the truncated number by 3 and get 0.999999999 which is less than 1. Converting to integer then gives 0. Solution when you do this? What you want to do is round the number, not truncate it. amnt100 = (int) floor(amnt * 100 + 0.5); --
|
Fri, 09 Mar 2001 03:00:00 GMT |
|
 |
Michael Smit #5 / 41
|
 SCANF() NEWBIE
Quote:
> I was hoping that someone could tell me why I can't scan in a number > and then multiply it times 100 without resulting in a number that's > off by one, but only in some cases???
Two problems. Floating point numbers are stored in a complicated binary (base 2) format. For many floating point numbers, there is no exact binary representation. For example, when I enter 67.60 it is actually stored as 67.5999985 (on my Win 95 box) and 67.61 is stored as 67.6100006. This is the closest that the computer can get. When you cast a float to an integer, it does not round to the nearest integer: it simply drops off the fractional part. So 6761.00006 truncates to 6761 (which is what you want) but 6759.99985 truncates to 6759 (which is not what you want). The simplest method to round to the nearest integer is to add 0.5 before truncating. int i; float f = /* something */; i = f+0.5; or more neatly: #define ROUND(x) (int)((x)+0.5) i = ROUND(f); -- ########################################################################
Emmenjay Consulting Pty Ltd http://www.zip.com.au/~emmenjay/ Computers *ARE* user-friendly. You just need to be properly introduced. --
|
Fri, 09 Mar 2001 03:00:00 GMT |
|
 |
George Swa #6 / 41
|
 SCANF() NEWBIE
Quote: >I was hoping that someone could tell me why I can't scan in >a [floating point] number >and then multiply it times 100 without resulting in a number that's >off by one, but only in some cases???
In the decimal arithmetic we are used to deal with, we are used to some fractions, like 1/3 or 2/3 not being able to be expressed cleanly as a percentage. Others, like 1/2, 1/4, 1/5, 1/10, 1/20, 1/100 can be expressed cleanly as a percentage. We don't lose precision with these fractions. As I am sure you know, we (almost always) store numbers in a binary format when we work with computers. This means we lose precision with any fraction whose denominator is not a power of two. --
|
Fri, 09 Mar 2001 03:00:00 GMT |
|
 |
Erik Trulsso #7 / 41
|
 SCANF() NEWBIE
Quote:
> I was hoping that someone could tell me why I can't scan in a number > and then multiply it times 100 without resulting in a number that's > off by one, but only in some cases??? > #include <stdio.h> > void main(void) > { > int pennies, nickels, dimes, quarters; > int dollar, amnt100; > float amnt; > printf("Enter dollar amount in decimal format: "); > scanf("%f", &amnt); > amnt100 = amnt * 100; > } > Input of 67.67 results in an assignment of 6766 to variable amnt100.
Almost certainly because many numbers can't be stored exactly as floating point numbers. In this case 67.67 might be internally represented ad 67.6699999 which when multiplied by 100 gives 6766.99999. When this number is converted to an int the fraction is discarded leaving you with 6766. Remember that just because a number can be exactly represnted in decimal (eg 67.67) it might not be exactly representable in binary. (Which most floating point systems use.) (Just as, for example, 1/3 can't be represnted exactly with decimal digits (0.3333333...) while it would be a perfectly nice number in base-3 notation. -- <Insert your favourite quote here.> Erik Trulsson
--
|
Fri, 09 Mar 2001 03:00:00 GMT |
|
 |
Peter Burde #8 / 41
|
 SCANF() NEWBIE
Quote:
> I was hoping that someone could tell me why I can't scan in a number > and then multiply it times 100 without resulting in a number that's > off by one, but only in some cases??? > Thanks, > Ron > #include <stdio.h> > void main(void) > { > int pennies, nickels, dimes, quarters; > int dollar, amnt100; > float amnt; > printf("Enter dollar amount in decimal format: "); > scanf("%f", &amnt); > amnt100 = amnt * 100; > } > Input of 67.67 results in an assignment of 6766 to variable amnt100. > Some other values: > Input amnt100 > 67.60 **6759** > 67.61 6761 > 67.62 6762 > 67.63 **6762** > 67.64 **6763** > 67.65 6765 > 67.66 6766 > 67.67 **6766** > 67.68 6768 > 67.69 6769
An old one but a good one. This is nothing to do with scanf(). It is the simple consequence of the fact that your ocmputer cannot store numbers of type float particularly accurately. In fact on all the computers Ive ever come across (recently!) it is impossible to store numbers such as 67.67 exactly as this becomes a non-terminating fraction in binary. It also looks as if your implementation of printf() may be truncating rather than rounding on "f" conversions. For this sort of application you might consider using the "double" data type although a better solution would be to work entirely in "cents" as an integer data type using code such as int pounds,pence; /* Well I am British ! */ int value; printf("Enter sum "); scanf("%d.%d",£s,&pence); value = pounds * 100 + pence; printf("Money is %d.%02d\n",value/100,value%100); Be careful with negative amounts ! Quote: > --
--
Home Page http://www.scit.wlv.ac.uk/~jphb/ --
|
Fri, 09 Mar 2001 03:00:00 GMT |
|
 |
Family80 #9 / 41
|
 SCANF() NEWBIE
HMMMM... int num; scanf("%d" &num); num*=100; Is your code like this? If so, it SHOULD work! dont forget the & in scanf!!! --
|
Fri, 09 Mar 2001 03:00:00 GMT |
|
 |
Gregory D. Hawke #10 / 41
|
 SCANF() NEWBIE
The %f format expects a pointer to a *double*, not a float. If you must use a float, the correct format is (hmm... access to long-term (and probably unreliable) storage) "%hf". -- Regards,
(Remove ".despam" to reply, please)
Quote: > I was hoping that someone could tell me why I can't scan in a number > and then multiply it times 100 without resulting in a number that's > off by one, but only in some cases??? > Thanks, > Ron > float amnt; > scanf("%f", &amnt);
--
|
Fri, 09 Mar 2001 03:00:00 GMT |
|
 |
Dan P #11 / 41
|
 SCANF() NEWBIE
Quote: >I was hoping that someone could tell me why I can't scan in a number >and then multiply it times 100 without resulting in a number that's >off by one, but only in some cases???
Do you have a clue about the floating point representations used by digital computers? If not, get one. NOW!!! Quote: > printf("Enter dollar amount in decimal format: "); > scanf("%f", &amnt); > amnt100 = amnt * 100;
amnt100 = amnt * 100 + 0.5; will give you the expected result for positive values of amnt. For negative values, subtract 0.5. If you want to do financial computations in C, the easiest way is to use double's and store the values expressed in cents, not dollars. Simply divide the results by 100 when you need to display them. Things are bit more complicated when a thoroughly rigorous approach is required, but my recipe above covers most usual situations. Dan -- Dan Pop CERN, IT Division
Mail: CERN - EP, Bat. 31 1-014, CH-1211 Geneve 23, Switzerland --
|
Fri, 09 Mar 2001 03:00:00 GMT |
|
 |
Gene Wirchen #12 / 41
|
 SCANF() NEWBIE
Quote:
>>I was hoping that someone could tell me why I can't scan in a number >>and then multiply it times 100 without resulting in a number that's >>off by one, but only in some cases??? >Do you have a clue about the floating point representations used by digital >computers? If not, get one. NOW!!!
Wow, Dan, are you ever friendly to newbies! If you can't be civil to newbies, how about leaving their questions to those of us who can? It's not as if he was asking us to do his homework for him, so your tone is out of line. Being a newbie, how would he know what the cause of the problem is? If he can't handle a program such as the one he posted, he isn't going to be able to dig into the minutiae of floating point representation quite yet. [snip] Sincerely, Gene Wirchenko Computerese Irregular Verb Conjugation: I have preferences. You have biases. He/She has prejudices. --
|
Sat, 10 Mar 2001 03:00:00 GMT |
|
 |
Francis Glassboro #13 / 41
|
 SCANF() NEWBIE
Quote: > My kludge would be > amnt100=amnt*100+.005; >which will effectively result in rounding. Others more knowledgeable >may have better ways.
These are always hard, but as you intend to round to an int you need to add .5 (though in this case the error will be way below that). Also the original writer should note that not all (in fact most) floats do not convert into ints. Even with a 64-bit int float covers many orders of magnitude more values. Francis Glassborow Chair of Association of C & C++ Users 64 Southfield Rd Oxford OX4 1PA +44(0)1865 246490 All opinions are mine and do not represent those of any organisation --
|
Sat, 10 Mar 2001 03:00:00 GMT |
|
 |
Dan P #14 / 41
|
 SCANF() NEWBIE
Quote: >The %f format expects a pointer to a *double*, not a float.
Since when? Quote: >If you must use a float, the correct format is (hmm... access to long-term >(and probably unreliable) storage) "%hf".
Bullshit. "%hf" is undefined behaviour. The *correct* format for a float is "%f" and it has been like that since K&R1. Dan -- Dan Pop CERN, IT Division
Mail: CERN - EP, Bat. 31 1-014, CH-1211 Geneve 23, Switzerland --
|
Sat, 10 Mar 2001 03:00:00 GMT |
|
|
Page 1 of 3
|
[ 41 post ] |
|
Go to page:
[1]
[2] [3] |
|