CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 21
  1. #1
    Join Date
    Aug 2006
    Posts
    515

    .11 * 100 trouble in C++

    My float variable contain .11 and I don't get the desired result of 11 from multiplication but simply numerica value .11 works.
    Code:
    short int test = .11 * 100; // test is right 11.
    
    // case 2
    float fVal = .11;
    short int test = fVal * 100; // now test is .10
    I tried various typcasting but it always is .10 when I use the float variable. How can I get the correct result?

    updated:
    compiler is VC++ 2005
    Last edited by zspirit; April 27th, 2007 at 11:59 AM.

  2. #2
    Join Date
    Aug 2000
    Location
    West Virginia
    Posts
    7,721

    Re: .11 * 100 trouble in C++

    1) 0.11 can not be stored exactly ... there are numerous threads
    on this.

    2) your calculations are not the same. In the first calculation 0.11
    is a double , in the second it it a float

  3. #3
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,398

    Re: .11 * 100 trouble in C++

    It is impossible to get "a correct result" in such a case. It would be the same as to exactly express the 1/3 with a decimal fraction (0.3333333333....)

  4. #4
    Join Date
    Oct 1999
    Location
    ks
    Posts
    523

    Re: .11 * 100 trouble in C++

    also try "* 100.0" rather than "* 100".

  5. #5
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,398

    Re: .11 * 100 trouble in C++

    Quote Originally Posted by jim enright
    also try "* 100.0" rather than "* 100".
    Why? What is the difference?

  6. #6
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,398

    Re: .11 * 100 trouble in C++

    Quote Originally Posted by zspirit
    ...
    Code:
    short int test = .11 * 100; // test is right 11.
    
    // case 2
    float fVal = .11;
    short int test = fVal * 100; // now test is .10
    To increase the precision of such calculations you should use double rather than float and long rather than short.

  7. #7
    Join Date
    Aug 2006
    Posts
    515

    Re: .11 * 100 trouble in C++

    I don't think .11 is any of those numbers which can not be represented, the first case stands example (.11 * 100 = .11 is hold correctly in that variable).

    if you check float fVal = .11, it also holds it correctly, things change when it is multiplied by 100 and yes float of course can hold 11.00 and so does short int.

    I am storing the value as short int, and I simply need to move that value from float to it. If you care curious shy short int, the value never exceeds 1,000 and the float is always 2 decimal places max.

    I am surprized any typcasting even does not work!

  8. #8
    Join Date
    Mar 2002
    Location
    St. Petersburg, Florida, USA
    Posts
    12,125

    Re: .11 * 100 trouble in C++

    Don't haqve a floating point binary calculator with me, but I can assure you that 0.1 is a repeating infinite binary pattern.
    TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
    2008, 2009,2010
    In theory, there is no difference between theory and practice; in practice there is.

    * Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions
    * How NOT to post a question here
    * Of course you read this carefully before you posted
    * Need homework help? Read this first

  9. #9
    Join Date
    Aug 2006
    Posts
    515

    Re: .11 * 100 trouble in C++

    Quote Originally Posted by TheCPUWizard
    Don't haqve a floating point binary calculator with me, but I can assure you that 0.1 is a repeating infinite binary pattern.
    what I am trying now is use doubles but even that has some issues.

    double dVal = (double) fVal;

    where as fVal = .11, dVal is .1099999...

    If I can transfer the fVal of .11 into dVal, that will make me happy..what should I do? typecasting does not work.

  10. #10
    Join Date
    Apr 1999
    Posts
    27,449

    Re: .11 * 100 trouble in C++

    Quote Originally Posted by zspirit
    I don't think .11 is any of those numbers which can not be represented,
    Care for a math lesson in binary?

    The only numbers that can be represented exacty on a binary system such as a computer are numbers that are sums of negative powers of 2. For example,

    0.5, 0.75, 0,125, 0.625, etc. can be represented exactly in binary, since (taking the first and second examples)

    0.5 = 1/(2^1) = 1/2
    0.75 = 1 / (2^1) + 1 / (2^2) = 1/2 + 1/4 = 3/4

    You can figure out the rest. A number such as 0.11 cannot be represented as sums of powers of 2 in the denominator, no matter how hard you try. It is a repeating, non-terminating binary number.

    0.11 = 0.00011100001010001111010111000010100011110101110000101001...

    There is no end to the string of digits, and note the pattern repeats after the 23rd (I hope I counted right) digit.

    So 0.11 cannot be represented exactly, as I've shown you here. If you want to see how to do the math to translate a decimal fraction to a binary fraction, you can go here:

    http://cs.furman.edu/digitaldomain/m...rac_to_bin.htm

    Regards,

    Paul McKenzie

  11. #11
    Join Date
    Apr 2007
    Posts
    43

    Re: .11 * 100 trouble in C++

    Quote Originally Posted by zspirit
    what I am trying now is use doubles but even that has some issues.

    double dVal = (double) fVal;

    where as fVal = .11, dVal is .1099999...

    If I can transfer the fVal of .11 into dVal, that will make me happy..what should I do? typecasting does not work.
    When you convert a float into a double, you've already lost the precision. Store it as a double to begin with, instead of a float. It's like taking a .jpg image and saving it as a .png or .gif, and hoping to get back the data you lost in the original compression. It's already gone.

    But what you're trying to do is going to be a problem no matter what. When a float or double value is converted to an integer, it simply truncates any non-integer data. Since the float representation of an integer can always look something like 'x.999999999999999', it will *always* truncate that data when cast to an int.

    There are ways to fix the problem, but you have to think about what you really want to do. If the result is 10.8, do you want that to be converted to 10, or 11? Do you want to round the number, or just truncate the decimal portion?

    It's a potentially dangerous operation, no matter what you do. And that's why it generates a compiler warning. The first thing I'd tell any new programmer is to always make sure the option "treat warnings as errors" is enabled. Warnings are the compiler's way of letting you know that you're doing things which might be dangerous, if you haven't thought them through. And that's a good thing. It's better to let the compiler catch errors than to find them yourself.

  12. #12
    Join Date
    Aug 2006
    Posts
    515

    Re: .11 * 100 trouble in C++

    Quote Originally Posted by kyoryu
    When you convert a float into a double, you've already lost the precision. Store it as a double to begin with, instead of a float. It's like taking a .jpg image and saving it as a .png or .gif, and hoping to get back the data you lost in the original compression. It's already gone.
    so I was relying on the fact the fVal still correctly says the value is .11 (you can see in debugger), so I thought converting it to double should go smooth since float can hold .11, double can too.

    Do you seem to suggest that even though fVal says it's value is .11, but in fact it's not?

    I am confused because if float can not hold .11 than it has enough decimal points to dislay it something else like say .109999 for, why it doesn't do that?

  13. #13
    Join Date
    Aug 2006
    Posts
    515

    Re: .11 * 100 trouble in C++

    Quote Originally Posted by Paul McKenzie
    Care for a math lesson in binary?

    The only numbers that can be represented exacty on a binary system such as a computer are numbers that are sums of negative powers of 2. For example,

    0.5, 0.75, 0,125, 0.625, etc. can be represented exactly in binary, since (taking the first and second examples)

    0.5 = 1/(2^1) = 1/2
    0.75 = 1 / (2^1) + 1 / (2^2) = 1/2 + 1/4 = 3/4

    You can figure out the rest. A number such as 0.11 cannot be represented as sums of powers of 2 in the denominator, no matter how hard you try. It is a repeating, non-terminating binary number.

    0.11 = 0.00011100001010001111010111000010100011110101110000101001...

    There is no end to the string of digits, and note the pattern repeats after the 23rd (I hope I counted right) digit.

    So 0.11 cannot be represented exactly, as I've shown you here. If you want to see how to do the math to translate a decimal fraction to a binary fraction, you can go here:

    http://cs.furman.edu/digitaldomain/m...rac_to_bin.htm

    Regards,

    Paul McKenzie
    Bear with me if I sound silly but in that case looks like .11 can not be truely represented even by double? Why should double help!

  14. #14
    Join Date
    Apr 2007
    Posts
    43

    Re: .11 * 100 trouble in C++

    Because you're confusing with the formatted output of the float value, with the actual float value. They're not the same.

    A float doesn't hold '.11'. It holds a collection of bits which are *approximately* .11. The debugger, when it outputs the value, does some internal conversions to decide how to print out the number.

    When you convert that .11 to a double, you're converting the bits which represent it into a double. And the double can only be an approximation of .11, anyway.

    When you cast from a float or double to an int, those "best-guess" efforts don't happen. They add complexity, so C just does the straightforward thing and lets you figure out what you actually want to happen. No point in incurring the cost for something that's not always needed.

    At any rate, casting from a float to an int is something you need to be careful with. You need to think about what you want the output to be for non-integer results. As an example, do you want 10.5 to be converted to 10, or 11?

    And using a double can help because it allows the internal representation of the value to be *closer* to the actual value you want. You're adding precision. But, double or float, the casting issue still remains.

    Another good idea when going between floats and ints is to only convert to an integer when you are absolutely sure you are done with all calculations.

    See what this code does:

    Code:
    	float fval = .11f;
    	float valAsFloatFromFloatByFloat = fval * 100.f;
    	int valAsIntFromFloatByFloat = fval * 100.f;
    
    	int valAsIntFromFloatByInt = fval * 100;
    	float valAsFloatFromFloatByInt = fval * 100;
    	printf("%d %d %d %d\n", (int)valAsFloatFromFloatByFloat, 
    							valAsIntFromFloatByFloat,
    							(int)valAsFloatFromFloatByInt,
    							valAsIntFromFloatByInt);
    Last edited by kyoryu; April 27th, 2007 at 03:14 PM.

  15. #15
    Join Date
    Dec 2005
    Posts
    254

    Re: .11 * 100 trouble in C++

    It seems that all you want to do is take a fractional decimal number and turn it into an int with the same digits? For example:

    .11 to 11
    .12 to 12
    .17 to 17
    .359 to 359
    .7 to 7

    and so on?

    However, as pointed out, fractions not in the series of fractional powers of two (as values or sums of values) cannot be represented in binary. I would attempt two solutions:

    First solution (rely on rounding):

    (int)(.11 * 100 + .005) should always produce 11
    (int)(.9 * 10 + .05) should always produce 9
    (int)(.359 * 1000 + .0005) should always produce 359

    The idea is to use a multiple of 10 that is equal to the number of decimal places, and add a value equal to 5 times a negative multiple of 10. The negative mulitiple would be one more than the multiple of the original number.

    Second solution:

    If the fractional numbers are inputs to your program, and if you have control of the input code, then you could have the inputs come in as strings. Use a library function ... ispunct() ... is one that I can think of, to remove the decimal point, and then convert the string to an int.

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured