问题
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