我的单元测试失败了Math.Tan(-PI/2)
在 .NET 中返回错误版本。
“预期”值取自 Wolfram 在线(使用 -Pi/2 的拼写常数)。
自己看看here http://www.wolframalpha.com/input/?i=tan%28-1.570796326794896557998981734272%29.
正如评论中正确观察到的那样,tan(-pi/2) 的数学结果是无穷大。然而,常数Math.PI
不能完美地代表 PI,因此这是一个“接近极限”的输入。
这是代码。
double MINUS_HALF_PI = -1.570796326794896557998981734272d;
Console.WriteLine(MINUS_HALF_PI == -Math.PI/2); //just checking...
double tan = Math.Tan(MINUS_HALF_PI);
Console.WriteLine("DotNET {0:E20}", tan);
double expected = -1.633123935319534506380133589474e16;
Console.WriteLine("Wolfram {0:E20}", expected);
double off = Math.Abs(tan-expected);
Console.WriteLine(" {0:E20}", off);
这是打印的内容:
True
DotNET -1.63317787283838440000E+016
Wolfram -1.63312393531953460000E+016
5.39375188498000000000E+011
我认为这是浮点表示的问题。
但奇怪的是,同样的事情在Java确实返回与 Wolfram 相同的值,直到最后一位数字 - 请参阅它在 Eclipse 中的评估。 (表达式被裁剪 - 你必须相信我,它们使用与MINUS_HALF_PI
above.)
True
DotNET -1.63317787283838440000E+016
Wolfram -1.63312393531953460000E+016
Java -1.63312393531953700000E+016
如您所见,区别在于:
- Wolfram 和 .NET 之间:
~5.39 * 10^11
- Wolfram 和 Java 之间:
=2.40 * 10^1
That's 十个数量级!
那么,您知道为什么 .NET 和 Java 实现差异如此之大吗?我希望他们都将实际的计算推迟到处理器。这个假设对于 x86 来说不现实吗?
Update
根据要求,我尝试在 Java 中运行strictfp
。不用找了: