1

I am trying to convert a char * containing just a floating point value to a type float, but both sscanf_s and atof both produce the same invalid result.

char t[] = "2.10";
float aFloat( 0.0f ), bFloat( 0.0f );

sscanf_s( t, "%f", &aFloat );
bFloat = atof( t );

Output:

aFloat: 2.09999990
bFloat: 2.09999990

When I looked at similar questions in an attempt to ascertain the answer I attempted their solutions to no avail.

Converting char* to float or double

The solution given here was to include 'stdlib.h', and after doing so I changed the call to atof to an explicit call 'std::atof', but still no luck.

Community
  • 1
  • 1
MikeO
  • 391
  • 4
  • 17
  • 6
    Not all values are exactly representable. Also see: http://stackoverflow.com/questions/588004/is-floating-point-math-broken – NathanOliver Jul 11 '16 at 16:43
  • Floating point != real. Welcome to binary. See @NathanOliver's link. – davidbak Jul 11 '16 at 16:44
  • 1
    Just a small correction to your question. Your result is perfectly valid and correct. Your assumptions and expectations are invalid. – Ped7g Jul 11 '16 at 16:48

2 Answers2

3

Unfortunately, not all floating point values can be explicitly represented in binary form. You will get the same result if you say

float myValue = 2.10;
GreatAndPowerfulOz
  • 1,767
  • 13
  • 19
  • 1
    Thank you. Does this not have a big impact on financial applications? – MikeO Jul 11 '16 at 16:57
  • 1
    @MikeO Not really, since you can always store the value of cents as an integer value, and then split that into parts of currency and cents by dividing/moding by 100 for display purposes. – Algirdas Preidžius Jul 11 '16 at 17:03
  • 1
    @MikeO It has a huge impact on financial applications if you're not prepared to handle imprecision. You need a consistent rounding strategy to avoid double-counting fractional pennies or losing them to truncation. Using a fixed-place numerical type for these calculations is strongly recommended. – tadman Jul 11 '16 at 17:27
  • @MikeO as my predecessor says it has tremendous impact for ex. if you add little float number to big one result will be incorrect. Lock at [this](http://www.tutorialspoint.com/viewproject.php?URL=compile_cpp11_online.php&PID=0Bw_CjBb95KQMajV1cmtFSFVWZ1E) – Logman Jul 11 '16 at 18:00
3

I see the excellent answer in comments is missing (or I didn't find it there easily) one other option how to deal with it.

You should have wrote, why you need floating point number. If you by accident happen to work with monetary amounts (and not too huge ones), you can create custom parser of input values, and custom formatter for value output, to read it as 64b integer (*100), and work in your whole application with 100*amount values. If you are working with really huge amounts, use some library for big numbers, or you may create your own, working with char* numbers.

It's a special case of Fixed-point arithmetic.

If you are interested into "just to solve this", without coding too much, head for big numbers library anyway, even the *100 fixed-point variant is easy to write with bugs - if it's your first time and you don't have enough resources to do it correctly (TDD advised).

But definitely learn how the numbers are stored in computer, and why float/double can't represent all numbers. Float 2.1 for computer (base 2 used internally) is similar case to human's 1/3, which can't be represented in base 10 without infinite number of decimal places (and how 1.0 == 0.99999... in base 10). (thanks @tobi303)


After reading your new comment, if "Does this not have a big impact on financial applications?"

Answer: nope, zero impact, nobody sane (and professional) would create financial application with floats or doubles.

Ped7g
  • 16,236
  • 3
  • 26
  • 63
  • 1
    "similar situation, like human base 10 format can't represent irrational numbers without infinite decimal places" sorry, I have to disagree. This has little to do with irrationales. Take 1/3 in base 10, this would be a much better equavalent of 2.1 (in base 10) not having a finite number of digits in base 2 – 463035818_is_not_an_ai Jul 11 '16 at 17:22