Math “pow” in Java and C# return slightly different results?
我是从C到JAVA移植程序。我面临这样一个事实
爪哇
1 | Math.pow(0.392156862745098,1./3.) = 0.7319587495200227 |
C.*
1 | Math.Pow( 0.392156862745098, 1.0 / 3.0) =0.73195874952002271 |
最后一个数字在进一步的计算中会产生足够的差异。有没有办法模仿C的战力?
桑克斯
为了确认Chris Shain写了什么,我得到了相同的二进制值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | // Java public class Test { public static void main(String[] args) { double input = 0.392156862745098; double pow = Math.pow(input, 1.0/3.0); System.out.println(Double.doubleToLongBits(pow)); } } // C# using System; public class Test { static void Main() { double input = 0.392156862745098; double pow = Math.Pow(input, 1.0/3.0); Console.WriteLine(BitConverter.DoubleToInt64Bits(pow)); } } |
二者产量:46047681178454313
换句话说,双精度值是完全相同的位模式,您看到的任何差异(假设您得到相同的结果)都是由于格式化而不是值的差异。顺便说一下,那个双精度的确切值是
1 | 0.73195874952002271118800535987247712910175323486328125 |
现在值得注意的是,浮点运算中可能会发生明显奇怪的事情,特别是当优化在某些情况下允许80位运算,而在其他情况下则不允许。
正如亨克所说,如果在最后一位或两位的差异导致了你的问题,那么你的设计就被破坏了。
如果您的计算对这种差异很敏感,那么您将需要其他措施(重新设计)。
this last digit leads to sufficient differences in further calculations
那是不可能的,因为它们是同一个数字。
1 | 0.73195874952002271118800535987247712910175323486328125. |
区别在于舍入:Java使用16个有效数字,而C是使用17。但这只是一个显示问题。
Java和C都返回来自Math.Pow的IEEE浮点数(特别是双点数)。您看到的差异几乎可以肯定是由于将数字显示为十进制时的格式设置。底层(二进制)值可能是相同的,而您的数学问题就在其他地方。
不管使用何种语言,17位数字的精度是任何IEEE浮点数都能做到的最好的:
http://en.wikipedia.org/wiki/double-precision_浮点_格式
浮点运算本身就不精确。您声称C答案是"更好的",但两者都不那么准确。例如,Wolfram Alpha(实际上更准确)给出了这些值:
http://www.wolframalpha.com/input/?I=功率%280.392156862745098%2c+1.0+%2f+3.0%29
如果一个单位的第十七位数字的差异导致后来的计算出错,那么我认为你的数学有问题,而不是Java的