开发者

What is causing this strange Mathematica result?

开发者 https://www.devze.com 2023-02-14 12:04 出处:网络
I\'ve run into what seems like a bug in Mathematica 8. I can\'t find anything related to it online, but I admit I\'m not exactly sure what to search for.

I've run into what seems like a bug in Mathematica 8. I can't find anything related to it online, but I admit I'm not exactly sure what to search for.

If I run this statement:

0.05 + .10 /. {0.15 -> "pass"}
1.04 + .10 /. {1.14 -> "pass"}
1.05 + .10 /. {1.15 -> "pass"}
1.15 /. {1.15 -> "pass"}

I get this output:

pass

pass

1.15

pass

Am I just overlooking something?

Edit: After reading the helpful discussion below, I changed my dispatch table to use a Which statement instead:

f[x_] := Which[x == 1.05, -1.709847, x == 1.10, -1.373823, 
  x == 开发者_JS百科1.15, -1.119214, x == 1.20, -0.9160143, x == 1.25, -0.7470223, x == 1.30, -0.6015966]

This seems to do the trick.


Welcome to the world of machine precision. If you examine 1.05 +.10 and 1.15 more closely, you'll see that they're not quite the same:

1.05 + .10 // FullForm

==> 1.1500000000000001`

1.15 // FullForm

==> 1.15`


In addition to incurring small errors when using MachinePrecision, the same floating-point calculation can produce slightly different results at different times of the day. This is not a bug, but rather a by-product of how modern hardware floating-point architectures work

This means you should not use operations like ReplaceAll that depend on knowing exact value of MachinePrecision numbers. Using == (and ===) might be OK because they ignore last 7 (respectively 1) binary digit of MachinePrecision numbers.

Using Mathematica arithmetic should give exact results regardless of time of day, you could use it for your example as follows (10 significant digits)

0.05`10 + .10`10 /. {0.15`10 -> "pass"}
1.04`10 + .10`10 /. {1.14`10 -> "pass"}
1.05`10 + .10`10 /. {1.15`10 -> "pass"}
1.15`10 /. {1.15`10 -> "pass"}

Update: What Every Computer Scientist Should Know About Floating-Point Arithmetic gives some more caveats about floating point arithmetic. For instance, page 80 gives examples of how different implementations of IEEE 754 give slightly different results, even despite being standard compliant


Your replacements only work on exact matches, whereas your While statement uses Equal. You can make the rule based approach work by using Equal as well.

0.05 + .10 /. {x_ /; x == 0.15 -> "pass"}
1.04 + .10 /. {x_ /; x == 1.14 -> "pass"}
1.05 + .10 /. {x_ /; x == 1.15 -> "pass"}
1.15 /. {x_ /; x == 1.15 -> "pass"}
0

精彩评论

暂无评论...
验证码 换一张
取 消