-9
?(1.0-0.9-0.1)
-0.000000000000000027755575615628914

?((double)1.0-(double)0.9-(double)0.1)
-0.000000000000000027755575615628914

?((double)1.0-(double)0.9-(double)0.1).GetType()
{Name = "Double" FullName = "System.Double"}

?((double)1.0-(double)0.9-(double)0.1).ToString()
"-2,77555756156289E-17"

How a Double.ToString() displays more chars(32) that double's precision(15-16)?

I expect that MyObject.ToString() represents just MyObject and not MyObject+SomeTrashFromComputer

Why

?0.1
0.1
?0.2-0.1
0.1
?0.1-0.1
0.0

BUT

?1.0-0.9-0.1
-0.000000000000000027755575615628914

WHY

?1.0-0.1-0.9
0.0

BUT

?1.0-0.9-0.1
-0.000000000000000027755575615628914
serhio
  • 28,010
  • 62
  • 221
  • 374
  • 5
    Actually your ToString() result has fewer (significant) digits. And it certainly has less chars, about half. – H H Oct 19 '12 at 17:15
  • 6
    You're confusing precision with significant figures ( http://en.wikipedia.org/wiki/Significant_figures ) and you should know that decimal fractions like 0.1 cannot be represented exactly in binary. Have you tried using the Decimal data type? – Andrew Morton Oct 19 '12 at 17:19
  • 1
    Precision is not accuracy, if you don't want the "trash", don't use Double, or start rounding. – Tony Hopkinson Oct 19 '12 at 17:21
  • 1
    @HenkHolterman I think the "some trash from computer" is indicating that he isn't aware of floating point errors, rather than not knowing scientific notation. – Servy Oct 19 '12 at 17:21
  • @Servy - but it's not certain/clear, my main reason to close. – H H Oct 19 '12 at 17:22
  • The leading zeros do not count towards the significant figures. – Andrew Morton Oct 19 '12 at 17:23
  • _How ... ToString() displays more chars(32)_ - it doesn't. Count them. It's 20 chars including the E17. – H H Oct 19 '12 at 17:25
  • It's probably a duplicate for this one but it's hard to tell: http://stackoverflow.com/q/1662600 – H H Oct 19 '12 at 17:28

3 Answers3

3

How a Double.ToString() displays more chars(32) that double's precision(15-16)?

It isn't displaying 32, it is displaying 17, leading zeros don't count. Floating point means it can keep track of changes in magnitude separately from changes in value.

I expect that MyObject.ToString() represents just MyObject

It does, there may be a slight difference due to the mechanics of floating point numbers, but the true number is represented by the string precisely.

not MyObject+SomeTrashFromComputer

There is no trash, there is floating point inaccuracy. It exists in decimal too, write down 1/3 as a decimal number exactly. You can't, it involves a repeating decimal place. Double's are stored in base 2, so even 0.1 creates a repeating "decimal".

Also note that you are getting two different representations because you are calling two different display methods. ToString has specific semantics, while your debugging window probably has different ones. Also look up scientific notation if you want to know what the E means.

Guvante
  • 18,775
  • 1
  • 33
  • 64
  • I understand that "1/3" is not accurate, because of devision, but I can't undestand why "0.1" is innacurate!!!? – serhio Oct 19 '12 at 17:29
  • @serhio A Double works in binary, not decimal. Try writing 0.1(decimal) in binary. You will get 0.0001100110011001100110011001100110011... – Andrew Morton Oct 19 '12 at 17:33
  • why 0.2-0.1 gives ALWAYS EXACTLY 0.1?? – serhio Oct 19 '12 at 17:39
  • why `1.0-0.1-0.9` is EXACTLY `0.0` but not `1.0-0.9-0.1`?? – serhio Oct 19 '12 at 17:44
  • 1
    @serhio `0.2-0.1` doesn't give exactly `0.1`, it simply results in a number that is rounded to `0.1` when displayed to you because that's the closest approximation. `why 1.0-0.1-0.9 is EXACTLY 0.0 but not 1.0-0.9-0.1?` The first one doesn't actually work out *exactly*, it simply rounds to the correct value "coincidentally". Both expressions result in floating point errors. – Servy Oct 19 '12 at 18:23
  • @serhio: Remember that all decimals are fractions. 0.1 is really 1/10, 0.25 is really 25/100 which can be simplified to 1/4. Given 1/10 and based 2 digits, write out that number. You can't you get 0.000110011 and so on. – Guvante Oct 19 '12 at 18:56
2

Check this System.Double

Remember that a floating-point number can only approximate a decimal number, and that the precision of a floating-point number determines how accurately that number approximates a decimal number. By default, a Double value contains 15 decimal digits of precision, although a maximum of 17 digits is maintained internally. The precision of a floating-point number has several consequences:

Two floating-point numbers that appear equal for a particular precision might not compare equal because their least significant digits are different.

A mathematical or comparison operation that uses a floating-point number might not yield the same result if a decimal number is used because the floating-point number might not exactly approximate the decimal number.

A value might not roundtrip if a floating-point number is involved. A value is said to roundtrip if an operation converts an original floating-point number to another form, an inverse operation transforms the converted form back to a floating-point number, and the final floating-point number is equal to the original floating-point number. The roundtrip might fail because one or more least significant digits are lost or changed in a conversion.

Mayank
  • 8,777
  • 4
  • 35
  • 60
1

I think you're unclear on two aspects of a floating point number; the precision and the range.

The precision of a floating point representation is how closely it can approximate a given decimal. The precision of a double is 15-16 digits.

The range of a floating point representation is related to how large or small of a number can be approximated by that representation. The range of a double is +/-5.0e-324 to +/-1.7e308.

So in your case, the calculation is precise to exactly 16 characters, and after that is not, as would be expected.

Some numbers that would seem simple are just not representable in standard floating point representation. If you require absolutely no deviation, you should use a different data type like decimal.

goric
  • 11,491
  • 7
  • 53
  • 69