Math “pow” in Java and C# return slightly different results?

与世无争的帅哥 提交于 2019-12-05 19:08:36

问题


I am porting program from C# to java. I've faced a fact that

Java

Math.pow(0.392156862745098,1./3.) = 0.7319587495200227

C#

Math.Pow( 0.392156862745098, 1.0 / 3.0) =0.73195874952002271

this last digit leads to sufficient differences in further calculations. Is there any way to emulate c#'s pow?

Thanx


回答1:


Just to confirm what Chris Shain wrote, I get the same binary values:

// 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));
    }
}

Output of both: 4604768117848454313

In other words, the double values are exactly the same bit pattern, and any differences you're seeing (assuming you'd get the same results) are due to formatting rather than a difference in value. By the way, the exact value of that double is

0.73195874952002271118800535987247712910175323486328125

Now it's worth noting that distinctly weird things can happen in floating point arithmetic, particularly when optimizations allow 80-bit arithmetic in some situations but not others, etc.

As Henk says, if a difference in the last bit or two causes you problems, then your design is broken.




回答2:


If your calculations are sensitive to this kind of difference then you will need other measures (a redesign).




回答3:


this last digit leads to sufficient differences in further calculations

That's impossible, because they're the same number. A double doesn't have enough precision to distinguish between 0.7319587495200227 and 0.73195874952002271; they're both represented as

0.73195874952002271118800535987247712910175323486328125.

The difference is the rounding: Java is using 16 significant digits and C# is using 17. But that's just a display issue.




回答4:


Both Java and C# return a IEEE floating point number (specifically, a double) from Math.Pow. The difference that you are seeing is almost certainly due to the formatting when you display the number as decimal. The underlying (binary) value is probably the same, and your math troubles lie elsewhere.




回答5:


Floating-point arithmetic is inherently imprecise. You are claiming that the C# answer is "better" but neither of them are that accurate. For example, Wolfram Alpha (which is much more accurate indeed) gives these values:

http://www.wolframalpha.com/input/?i=Pow%280.392156862745098%2C+1.0+%2F+3.0%29

If a unit's difference in the 17th digit is causing later computations to go awry, then I think there's a problem with your math, not with Java's implementation of pow. You need to think about how to restructure your computations so that they don't rely on such minor differences.




回答6:


Seventeen digits' precision is the best any IEEE floating point number can do, regardless of language:

http://en.wikipedia.org/wiki/Double-precision_floating-point_format



来源:https://stackoverflow.com/questions/10130997/math-pow-in-java-and-c-sharp-return-slightly-different-results

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!