admin管理员组

文章数量:1435859

I'm working on something that extracts a float from a string. I noticed that certain values result in slightly inaccurate float values. Some research on the subject pretty much has told me to either:

  • employ a precise float library
  • maybe switch to a larger data type (double) for a wider range of accuracy
  • use integer based math

I would prefer not having to do any of these (especially that last one), but instead create a function that "rounds" a float up until it matches the string representation. I did some some basic math and realized that this did happen (at least in my example).

In my example, I had a string with the value "0.04". When I use std::stof() on it, this results in a value of 0.0399999991. The minimum amount I have to add to that float value for it to match the string (at least until my string's decimal point) is 0.0000000019 so it then converts to 0.0400000010. I figured this out by just adding until the shift happened.

Is there an already existing method of doing such a calculation for all floats? If not, I'm worried I would have to do a loop to keep increasing by 0.0000000001. However, I'm not sure how I can programmatically conclude success given that switching 0.0399999991 back to a string results in a string of "0.04" again.

I'm working on something that extracts a float from a string. I noticed that certain values result in slightly inaccurate float values. Some research on the subject pretty much has told me to either:

  • employ a precise float library
  • maybe switch to a larger data type (double) for a wider range of accuracy
  • use integer based math

I would prefer not having to do any of these (especially that last one), but instead create a function that "rounds" a float up until it matches the string representation. I did some some basic math and realized that this did happen (at least in my example).

In my example, I had a string with the value "0.04". When I use std::stof() on it, this results in a value of 0.0399999991. The minimum amount I have to add to that float value for it to match the string (at least until my string's decimal point) is 0.0000000019 so it then converts to 0.0400000010. I figured this out by just adding until the shift happened.

Is there an already existing method of doing such a calculation for all floats? If not, I'm worried I would have to do a loop to keep increasing by 0.0000000001. However, I'm not sure how I can programmatically conclude success given that switching 0.0399999991 back to a string results in a string of "0.04" again.

Share Improve this question edited Nov 16, 2024 at 19:51 Remy Lebeau 602k36 gold badges508 silver badges853 bronze badges asked Nov 16, 2024 at 18:39 RickyRicky 8832 gold badges15 silver badges35 bronze badges 8
  • 4 There are an infinite number of numeric values, but only a finite number of float values; you cannot represent every possible numeric value in a float. Nor in a double or in any numeric type you might invent so long as the memory on your system is finite. – Pete Becker Commented Nov 16, 2024 at 18:49
  • 5 Re: "this results in a value of 0.0399999991" -- no, it results in a value that, when converted to text by some unspecified mechanism, becomes "0.0399999991". Don't confuse the text representation of a value with the actual floating-point value. – Pete Becker Commented Nov 16, 2024 at 18:56
  • 5 0.0399999991 is more accurate than 0.0400000010, why do you want the less accurate value? – Alan Birtles Commented Nov 16, 2024 at 19:04
  • 2 If you are dealing with money, instead of using a floating point type use a 64 bit integer and store the value in cents. Then cents / 100 is dollars and cents % 100 is the cents. Then you don't have to worry about floating point inaccuracies. – NathanOliver Commented Nov 16, 2024 at 19:19
  • 2 This question is similar to: Is floating-point math broken?. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. – Richard Critten Commented Nov 16, 2024 at 20:02
 |  Show 3 more comments

3 Answers 3

Reset to default 3

The answer depends to some extent on what you are trying to do with the numbers after you extract them from the string.

If you want to print them out for human consumption later, or if you want to embed them in other strings that get written out in some other format, and if it's important that you print out the value exactly as input, no matter what, then you might not want to convert to float, or double, at all. If there's no need to do math on them, you might as well not convert to a numeric type at all, but rather carry them around as strings.

But if you have some math you need to do on them, it will be easiest if you use one of C++'s native floating-point types, except: they're going to have this problem.

You can minimize — and in many case, eliminate — the problem by printing your numbers out at the end (or converting them to strings) with the precision limited to something that is reasonable for your numbers. For example, in the example that you gave, if you were to print the value f back out using

std::cout << std::fixed << std::setprecision(2) << f;

then you would see 0.04 as you expect.

(See How to set the output precision to 2 decimal places in C++ for more on this technique.)

But you can not, repeat not, "fix" this problem by adding 0.0000000001, or anything like that. The problem is not that atof wrongly converted the string "0.04" to the floating-point value 0.0399999991. The problem is that types float and double can not represent the value 0.04 exactly, at all, period. If atof couldn't store the value 0.04 into a floating-point variable, then you can't do so by adding 0.0000000009, either.

The fundamental issue is that floating-point values in C++ (and most languages) are represented internally in binary, which can't represent multiples of 0.1 or 0.01 exactly. (This is similar to the way we can't exactly represent the fraction 1/3 in decimal.). See the canonical SO questions Why are floating point numbers inaccurate and Is floating-point math broken for more (much more) on this topic. The bottom line is that when you convert the decimal value 0.04 to a single-precision float, the closest you can get is a binary fraction which is equivalent to the decimal fraction 0.039999999105930328369140625. As a double, the closest you can get is 0.040000000000000000832667268468867405317723751068115234375. You just can't get any closer than that.

In some languages — but not C or C++ — the default method for converting floating-point values for output employs a reasonably sophisticated algorithm to automatically, in effect, round to an appropriate number of digits when printing, which would tend to give you exactly what you want in cases like these, without your having to set the precision explicitly. There's probably a decent way to utilize this algorithm (known as "Errol") in a C++ program, but I don't know what it is.

Common float is 32-bits, so float can only encode about 232 different values. Text can represent unlimited number of values, so a reasonable expectation is that only a subset is possible to achieve OP's goal. @Pete Becker


doing such calculation for all floats?

Yes, if input does not use too many significant decimal digits.
0.0399999991 has 9 significant decimal digits.

With common float, all decimal text versions of a value in the [-FLT_MAX ... FLT_MAX] range that uses FLT_DIG (e.g. 6) or fewer significant decimal digits will convert to a float via stof(), that when printed, using the same number of significant decimal digits, will present the same. This float may differ a little in value from the text, yet will match (round) when not too many significant decimal places are printed.


Floating point numbers are (usually) represented in binary, which can not represent decimal fractions exactly (except for a few ones), so the round trip "textual decimal representation --> binary floating point --> textual decimal representation" will fail most of the time.

What you can do is to e.g. printf in C to the wanted number of decimals. If you need exactly two decimals, use integers expressed in hundreths.

本文标签: cCan I convert a string to float with a minimum decimal point precision valueStack Overflow