December 7th, 2004, 10:20 PM
loss of precision float to int in c
I'm trying to do:
copyinput = (int) (input * 100);
input lets say is: 8888.88
copyinput holds: 888887
How can I overcome this inprecision without big computational efforts.
December 7th, 2004, 11:19 PM
why not just leave it as a float?
True happiness is not getting what you want, it's wanting what you've already got.
December 7th, 2004, 11:44 PM
floats and float math is inherently imprecise.
You can round, you can do whatever, and some tiny discrepency will still creep in.
What is your target, though?
December 8th, 2004, 02:28 AM
You could always do
copyinput = (int) (input * 100 + 0.5);
which will round off, rather than down.
December 8th, 2004, 08:09 AM
Target is that I'm in college learning all this, and we are to convert float to int without doing:
Originally Posted by jasonvene
copyinput = (int) (input * 100 + 0.5).
Tutor says: If I'm doing that I would have to justify to him
why I'm using the precise (0.5) adition.
As the difference (input to next upper natural number) is not the same at all times I'd like to establish the precise difference between the inprecision and the next natural number. So that I can then add that inprecision to the number(input) to get the next natural number.
I hope I expressed this clearly and understandably.
December 8th, 2004, 10:48 AM
you will have to break the float in the integer part and the decimal part. do the operations and add them together. i guess it is easier if you do this at the end of the float operations, right before the conversion to int. there are some functions for this like modf(). you will also have to decide how to round the integers.
December 8th, 2004, 03:11 PM
Sometimes it takes clairvoyance to provide the answer a professor is insisting upon :p
I don't recognize the point he's trying to make about justification of the rounding, except the general concept of math proofs or "showing one's work on paper" in algebra or the calculus.
Anyway, floats have a tendency to loose precision, as you recognize. You can't always determine what the original intent for a particular number was supposed to be.
Take two floats, d1 and d2, set both equal to 10.1.
Now, d3 = d1 + d2;
d3 should be 20.2. The computer "thinks" it's 20.200001.
Now, do the same thing in doubles.
Should be 20.2 again, but the computer "thinks" is 20.199999999999999
Now, given d3 in either case, how could you guess what the number ought to be? You can't.
There is no choice but to round.
This applies to all operations, as you've observed with multiplication. There are values ( be it type double, float - whatever "real" type) which can rather accurately depict the original, but as you've observed this isn't consisitent.
There is no choice but to round, but how can be a valid question. Generally speaking, in order to pin down what the floating point value should "read" or "represent" you must decide on a level of precision. This is applicable beyond programming; virtually all scientific or related industrial calculations are pegged to a tolerance of some limit. It's the specification of that limit that gives you justification for rounding.
Conversion to an integer via multiplication by 100 gives you some authority to round to two decimal places (at least from a non-programming point of view). Lacking decimal places, though, integers don't lend themselves to rounding through addition by 0.5, and as you've observed that addition is, itself, possibly prone to an error.
Now, consider modf, as suggested, with the example values above. Using doubles, the modf result of "d3" is 20.00000, which we'll call d4. To get the fractional part, d5 = d3 - d4, which gives the maddening answer: 0.19999999999999929
Floats fare no better. While d4 provides the reassuring 20.0, d5 returns a frustrating: 0.20000076
Though, you'll recognize, for these particular values, floats would naturally truncate in your integer conversion (without .5 addition) to a "good" result. Other values, however, may not.
At this point I must chuckle at the futility.
BTW, in doubles, d3 = 8888.88 will cause any "print" or "use" of d3 to "think" it's 8888.8799999999992. Cute, eh? That's without ANY math operation upon d3!
In any case, your justification for rounding is clear. The value 0.5 is appropriate as part of a "5/4 rounding method" on paper, but there are exceptions. Consider 8888.845. A float stores this value as 8888.8447, will not round to two decimal places as you expect (it should become 888885 in your integer conversion, if everything were exact). It won't. It will become 888884.
Interestingly, even with a double, the value is represented at 8888.8449999999993, and so
int val = (int)( d3 * 100 +.5) results in 888884.
int val = ((int)( d3 * 1000 + 5) / 10;
results in 888885!
So, what's a programmer to do?
Clairvoyance, I'm afraid.
Last edited by jasonvene; December 8th, 2004 at 03:18 PM.
December 10th, 2004, 05:19 PM
Originally Posted by jasonvene
Here it is your answer captures all that I needed to understand and need for the problem at hand:
' provide the answer a professor is insisting upon '
Well his point is I think that we need to understand the inprecision of floats and doubles as whole when programming a particular problem. I think it's a good exercise to get our head round this ourselves.
I thank all for their interesting and very helpfull contributions, especially you 'Jasonvene'.
ps: had to study hard for some project thats why the late reply.
December 10th, 2004, 05:33 PM
Maybe it's easier to understand the imprecision if you consider it in it's simplest terms. On my 32-bit machine an integer is 32 bits and so's a float (a double is 64). How does one get a zillion times the range with a float when the number of bits available to encode it is the same? Magic? Nope, loss of precision.
Functionality rules and clarity matters; if you can work a little elegance in there, you're stylin'.
If you can't spell "u", "ur", and "ne1", why would I hire you? 300 baud modem? Forget I mentioned it.
October 8th, 2012, 08:51 PM
Percision Issue when converting from float to int : Thanks Jasonvene
I am just beginning to learn how to program in C with my son who is taking it in school. The teacher assigned a problem to figure out the domination of change ($) received from a customer.
I was having an issue with myreturn_int loosing precision causing the end value to be a penny short when the change was $x.y6 to $x.y8.
float cash, sale, myreturn; \\ cash=$10, sale=$7.53
myreturn = cash - sale; \\ myreturn=$2.47
myr = (myreturn * 100); \\ myr=246.9999
myreturn_int = myr; \\ myreturn_int=246
BUT after reading your answer/suggestion, I tried:
myr = (myreturn * 1000 + 5)/10; \\ myr=247.49
myreturn_int = myr; \\ myr=247
Now the program works great and I am never a penny short.
I could have just tried the rounding function but we have only learned up to chapter 4 of the "Programming in C" by Kochan book.
I'm glad I discovered this forum online. It's a great help for me.
Thanks Jasonvene for a wonderful explanation.
October 9th, 2012, 02:30 AM
IMO, in order to correctly convert the float to int, you need to round using .5 -- so what's wrong with justifying it? If he said that, maybe he wants you to think about it and explain why this is a good way to do it.
Originally Posted by Silvanus
Just because you are asked to justify something does not mean it's wrong. It means you understand why it's necessary.