[英]I have tried using long both as the variable type as well as the return type of the function but still it is overflowing. I cannot understand why?
[英]Why is this long overflowing to -1, instead of the minimum value for the type?
我有以下的代码,返回时完全二叉树是树的节点数目layer
的层身材:
public static long nNodesUpToLayer(int layer) {
if (layer < 0) throw new IllegalArgumentException(
"The layer number must be positive: " + layer );
//At layer 0, there must be 1 node; the root.
if (layer == 0) return 1;
//Else, there will be 1 + 2 * (the number of nodes in the previous layer) nodes.
return 1 + (2 * nNodesUpToLayer(layer - 1));
奇怪的是,当我在函数中输入63
(产生这个的最小值)时,它会让我回到-1
。 在62
,它返回9223372036854775807
,所以这似乎是由溢出引起的。
它不应该让我回到Java长期的最小值+它溢出的数量吗? 无论我给它的输入(通过62
),它总是会返回-1
而不是一个看起来随机的数字,我期望从溢出。
我不完全确定如何调试它,因为它是递归的,并且只有在函数达到基本情况时才会评估我感兴趣的值。
你是对的,它是64位有符号整数的溢出错误。 它变为-1
而不是最小整数值的原因是因为你加倍,而不是简单地添加一个。
在Two's Complement中的 9223372036854775807
是63 1
s:
0111 1111 ... 1111 1111
要以二进制加倍,只需执行左移:
1111 1111 ... 1111 1110
但是,Two's Complement中的这个数字不是两倍9223372036854775807
,而是-2
。 然后,当然,在返回获得-1
结果之前,先添加1
。
实际上,它会返回正确的金额。 它只是“它溢出的数量”是完全正确的答案-1
:)
考虑一下:
对于n
层,完整二叉树中的节点数为2^n - 1
。 因此,它的二进制表示为0000...00111...111
,其中数量1
s是精确的层数减1。一旦你到达的长度long
你被困在被截断的11...11
,正好是-1
我总是喜欢用这样的东西进行可视化。
(min long)
v
<--------------------||--------------------------------------->
^ ^
(max long, n) -1
其中n
是9223372036854775807 - 在乘以2之前的值。而不是乘法,而是将其视为加法。 n + n
。 通过在数字线上看到它,你可以看到你最终在-2。 你基本上已经超过了大多数负数。
因此,与其他人相比,我的答案提供了一些有意义的东西,在这种情况下,一个有用的工具是将算术分成多行以便进行调试。 你可以写:
int a = nNodesUpToLayer(layer - 1);
int b = 2 * a;
int c = 1 + b;
return c;
您实际上正在按照您的预期强制执行操作顺序(这可能会帮助您实现程序按照您希望的顺序执行操作),但它也允许您进入调试器并查看中间程序你的计算值。 在这里你会注意到b == -2
。 为什么b == -2
? 好吧,一定是因为2 * a == -2
等。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.