#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2004
    Posts
    6
    Rep Power
    0

    loss of precision float to int in c


    I'm trying to do:

    int copyinput;
    float input;

    copyinput = (int) (input * 100);


    input lets say is: 8888.88

    copyinput holds: 888887

    How can I overcome this inprecision without big computational efforts.
    Thanks.
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jan 2004
    Location
    Constant Limbo
    Posts
    989
    Rep Power
    363
    why not just leave it as a float?
    True happiness is not getting what you want, it's wanting what you've already got.

    My Blog
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2003
    Posts
    705
    Rep Power
    12
    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?
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    May 2004
    Location
    Adelaide, Australia
    Posts
    880
    Rep Power
    11
    You could always do
    copyinput = (int) (input * 100 + 0.5);

    which will round off, rather than down.
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2004
    Posts
    6
    Rep Power
    0
    Originally Posted by jasonvene
    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?
    Target is that I'm in college learning all this, and we are to convert float to int without doing:

    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.
  10. #6
  11. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Location
    Baltimore, MD
    Posts
    229
    Rep Power
    12
    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.
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2003
    Posts
    705
    Rep Power
    12
    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.

    However, this:

    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 02:18 PM.
  14. #8
  15. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2004
    Posts
    6
    Rep Power
    0
    Originally Posted by jasonvene
    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.

    So, what's a programmer to do?

    Clairvoyance, I'm afraid.
    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'.
    Kind regards,

    Silvanus

    ps: had to study hard for some project thats why the late reply.
  16. #9
  17. Lord of Dorkness
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2004
    Location
    Central New York. Texan via Arizona, out of his element!
    Posts
    8,524
    Rep Power
    3314
    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.
    DaWei on Pointers Politically Incorrect.
  18. #10
  19. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2012
    Posts
    1
    Rep Power
    0

    Percision Issue when converting from float to int : Thanks Jasonvene


    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.
  20. #11
  21. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2004
    Posts
    20
    Rep Power
    0
    Originally Posted by Silvanus
    Target is that I'm in college learning all this, and we are to convert float to int without doing:

    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.
    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.

    Just because you are asked to justify something does not mean it's wrong. It means you understand why it's necessary.

IMN logo majestic logo threadwatch logo seochat tools logo