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"}
精彩评论