-1

Now i know to use the method of float.Parse but have bumped into a problem.

I'm parsing the string "36.360", however the parsed float becomes 36.3600006103516.

Am i safe to round it off to the 3 decimal places or is there a better tactic for parsing floats from strings.

Obviously i'm looking for the parsed float to be 36.360.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Abstract
  • 455
  • 1
  • 3
  • 12

5 Answers5

3

This has nothing to do with the parsing, but is an inherent "feature" of floating-point numbers. Many numbers which have an exact decimal representation cannot be exactly stored as floating-point number, which causes such inequalities to appear.

Wikipedia (any many articles on the web) explain the issues.

Lucero
  • 59,176
  • 9
  • 122
  • 152
2

Floating point numbers are inherently prone to rounding errors; even different CPU architectures would give a different number out in the millionths decimal place and beyond. This is also why you cannot use == when comparing floating point numbers....they'll rarely evaluate as equal because of floating point precision errors.

saluce
  • 13,035
  • 3
  • 50
  • 67
  • 2
    "Never be equal" is a popular misunderstanding. There are billions of values that `float`s can store precisely. Many whole numbers for instance; you can store 1234567.0 in a float and get accurate results when comparing. They're just not very good at storing floating point numbers. – Mr Lister Apr 09 '12 at 14:12
  • @MrLister +1, and furthermore, many fractional numbers can also be represented exactly in the binary floating point system (for example, 0.5). In fact, every float or double bit pattern represents either inifinity, NaN, or some exact numeric value. – phoog Apr 09 '12 at 15:00
  • @MrLister True, but there are billions of values that `float`s cannot store precisely, so unless you can guarantee that a variable contains a value that can be exactly represented by a `float`, using an equality comparison leads to more problems than it is worth. Code example: `debug.print ((float)3.141 == 3.141 ? true : false)` generates a `false`, even though it's obvious (to us) that it should be true. – saluce Apr 09 '12 at 15:04
  • Yes, and it's difficult to explain _why_ 36.36 isn't representable exactly, while, for instance, 36.375 would be. ("Because you'd need only 8 bits of mantissa" isn't much of an explanation there, is it) – Mr Lister Apr 09 '12 at 15:12
  • @saluce the number of values that cannot be stored precisely in a float is infinite, as is the number of values that cannot be stored precisely in a decimal. – phoog Apr 09 '12 at 18:31
  • @MrLister it's fairly easy to explain why 36.36 isn't representable exactly in a float; it's because 36/100 can't be reduced to a fraction whose denominator is a power of two. It is finitely representable as a decimal fraction because its denominator has no prime factors other than 2 and 5 (the prime factors of 10). Generally: a fraction has a finite representation in base X iff its denominator contains no prime factors other than the prime factors of x. – phoog Apr 09 '12 at 18:34
1

There are limits in the precision of floating point numbers. Check out this link for additional details.

If you need more precise tracking, consider using something like a double or decimal type.

Community
  • 1
  • 1
Jonathan Wood
  • 65,341
  • 71
  • 269
  • 466
1

This is due to the fact that float or double are both stored in such a way that it is a mathematical process to read the value from memory. If you want to store the value as the actual value a better choice would be decimal.

Per the MSDN Page on System.Decimal:

The Decimal value type is appropriate for financial calculations requiring large numbers of significant integral and fractional digits and no round-off errors. The Decimal type does not eliminate the need for rounding. Rather, it minimizes errors due to rounding.

Adam Gritt
  • 2,654
  • 18
  • 20
  • reason for concluding this was answer was due to the fact of quoting the msdn page and also pointing out the financial calculations. Perfectly answered the situation. Thanks! – Abstract Apr 09 '12 at 14:27
  • I'm not sure what you mean by "mathematical process to read the value from memory". In fact, the real "problem" with `float` and `double` is that they store values as base-2 fractions, and that there are some numbers with a finite base-10 representation but an infinite base-2 representation. – phoog Apr 09 '12 at 14:55
  • @phoog - What I meant is that when the processor reads the `float` or `double` from memory it must parse the bits to pull out the Sign, Exponent and Mantissa and then do the math as shown on [Wikipedia](http://en.wikipedia.org/wiki/Double-precision_floating-point_format). Due to the math involved you end up with an approximation of the value rather than the exact value. The only exact values that a `float` or `double` can provide is 1 and power of 2's, and even then it is dependent upon the processor to do the math correctly. Whereas an Integer in memory will always have an exact value. – Adam Gritt Apr 09 '12 at 15:59
  • You overstate the so-called inaccuracy of floating-point numbers. For example, when the processor performs operations on floating-point values in memory, it does not parse sign, exponent, or mantissa; rather, it copies the values to the floating-point registers, and uses floating-point opcodes to perform the operation. Furthermore, integer values up to the precision of the type in question can be represented exactly. For example, `double` *can represent every `int` value exactly, and several thousand more integers, to boot.* That's why there's an implicit conversion from `int` to `double`. – phoog Apr 09 '12 at 16:31
  • Also, any mathematical operation performed by a computer is "dependent upon the processor to do the math correctly". Processors are no less correct in performing floating-point arithmetic than integer arithmetic, pentium FDIV bug excepted: http://en.wikipedia.org/wiki/Pentium_FDIV_bug – phoog Apr 09 '12 at 16:33
1

That's not an odd issue at all, it's just one of the charming features of floats you'll always going to run into. floats can't express that kind of decimal values accurately!

So if you need the result to be exactly 36.36, use a decimal rather than a float.
Otherwise, you're free to round off. Note that rounding won't help though, because it won't be exactly 36.36 after rounding either.

Mr Lister
  • 45,515
  • 15
  • 108
  • 150