Java NumberFormatException:无限或 NaN
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18028454/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
NumberFormatException: Infinite or NaN
提问by Kareem
I have a method that takes n and returns nth Fibonacci number. Inside the method implementation I use BigDecimal
to get the nth Fibonacci number then I use method toBigInteger()
to get the number as a BigInteger
object and that's surely because I am working with huge numbers in my application.
我有一个接受 n 并返回第 n 个斐波那契数的方法。在方法实现中,我BigDecimal
用来获取第 n 个斐波那契数,然后我使用方法toBigInteger()
将数字作为BigInteger
对象获取,这肯定是因为我在我的应用程序中处理大量数字。
I keep getting correct results until I pass 1475as an argument for my method. I get NumberFormatException: Infinite or NaN
in this case without any clear reason for me.
我一直得到正确的结果,直到我通过1475作为我的方法的参数。我NumberFormatException: Infinite or NaN
在没有任何明确理由的情况下陷入这种情况。
Could you please explain me why am I getting this exception?
你能解释一下为什么我会收到这个异常吗?
Here's my method:
这是我的方法:
BigInteger getFib(int n){
double phi = (1 + Math.sqrt(5))/2;
double squareRoot = (Math.sqrt(5)) + (1/2);
BigDecimal bd = new BigDecimal(Math.floor(Math.pow(phi, n)/(squareRoot)));
return bd.toBigInteger();
}
采纳答案by BlackJoker
Your Math.pow(phi, n)
is too big(Infinity),double is unable to store it,use BigDecimal instead.
你Math.pow(phi, n)
太大了(Infinity),double 无法存储它,请改用 BigDecimal。
How about the flowing:
流水如何:
static BigInteger getFib(int n) {
BigDecimal x1 = new BigDecimal((1 + Math.sqrt(5)) / 2);
BigDecimal x2 = new BigDecimal((1 - Math.sqrt(5)) / 2);
return x1.pow(n).subtract(x2.pow(n))
.divide(new BigDecimal(Math.sqrt(5))).toBigInteger();
}
from the formula:
从公式:
UPDATE:the above way is incorrect,because Math.sqrt(5) does not has enough precision as the comment said. I've tried to culculate sqrt(5) with more precision using Netown's method,and found out that x1.pow(n).subtract(x2.pow(n)).divide(...)
is very time-consuming,it spended about 30 seconds for n = 200 in my computer.
更新:上述方式是不正确的,因为 Math.sqrt(5) 没有足够的精度作为评论说。我尝试使用 Nettown 的方法更精确地计算 sqrt(5),发现这x1.pow(n).subtract(x2.pow(n)).divide(...)
非常耗时,在我的计算机中 n = 200 花费了大约 30 秒。
I think the recursive way with a cache is mush faster:
我认为使用缓存的递归方式更快:
public static void main(String[] args) {
long start = System.nanoTime();
System.out.println(fib(2000));
long end = System.nanoTime();
System.out.println("elapsed:"+ (TimeUnit.NANOSECONDS.toMillis(end - start)) + " ms");
}
private static Map<Integer, BigInteger> cache = new HashMap<Integer, BigInteger>();
public static BigInteger fib(int n) {
BigInteger bi = cache.get(n);
if (bi != null) {
return bi;
}
if (n <= 1) {
return BigInteger.valueOf(n);
} else {
bi = fib(n - 1).add(fib(n - 2));
cache.put(n, bi);
return bi;
}
}
It spend 7 ms in my computer for n = 2000.
对于 n = 2000,它在我的计算机上花费了 7 毫秒。
回答by morgano
Your problem is here:
你的问题在这里:
BigDecimal bd = new BigDecimal(Math.floor(Math.pow(phi, n)/(squareRoot)));
the result of Math.floor(Math.pow(phi, n)/(squareRoot))
is giving you either infinite or NaN.
的结果Math.floor(Math.pow(phi, n)/(squareRoot))
是给你无穷大或 NaN。
According to the BigDecimal javadocthat constructor (BigDecimal(double)
) could throw a NumberFormatException
if you use a double with value infinite or NaN
根据BigDecimal javadoc,如果您使用值为无穷大或 NaN 的 double ,则构造函数 ( BigDecimal(double)
) 可能会抛出 aNumberFormatException
回答by Stephen C
This is not cause of the INF's / NaN's but it is definitely wrong. This ...
这不是 INF / NaN 的原因,但这绝对是错误的。这个 ...
double squareRoot = (Math.sqrt(5)) + (1/2);
... is equivalent to this ...
……相当于这个……
double squareRoot = Math.sqrt(5));
... because (1/2)
is an integer division, returning an integer value; i.e. zero.
... 因为(1/2)
是整数除法,返回整数值;即零。
In fact, I think the most likely explanation for the INF / NaN is that "phi1475" is too large to be represented as a double
. So the pow
method is returning INF
... which is the way that "too large" is represented as a floating number in Java.
事实上,我认为对 INF / NaN 最可能的解释是“phi 1475”太大而无法表示为double
. 所以该pow
方法正在返回INF
......这是“太大”在Java中表示为浮点数的方式。
If you want to compute Fibonacci numbers this way, you need to use a representation that is capable of representing the really large numbers involved ... and represent them with sufficient accuracy. The Java double
type cannot do this. And indeed, it is hard to do the computation using BigDecimal
... as the comments on the accepted answer demonstrate!
如果您想以这种方式计算斐波那契数,您需要使用能够表示所涉及的真正大数的表示法……并以足够的精度表示它们。Javadouble
类型不能这样做。事实上,BigDecimal
正如对已接受答案的评论所表明的那样,很难使用...进行计算!
I'd recommend using the recurrence relation. It is going to be much simpler ... and probably more efficient as well.
我建议使用递归关系。它会更简单……而且可能也更高效。
回答by Hossein Nasr
It's not a good idea to create BigDecimal
with float or double because its again limit to the range of them
you must create a BigDecimal at first and do some operation with its functions like:
BigDecimal
使用 float 或 double创建不是一个好主意,因为它再次限制了它们的范围,您必须首先创建一个 BigDecimal 并对其功能进行一些操作,例如:
BigDecimal a;
BigDecimal b;
x1.pow(b);