Java 求解'后的边界阵列索引;可能的精度损失';编译错误
工作:意味着没有精度错误::只是数组超出范围Java 求解'后的边界阵列索引;可能的精度损失';编译错误,java,arrays,long-integer,Java,Arrays,Long Integer,工作:意味着没有精度错误::只是数组超出范围 long a[] =new long[1000000]; int no=2,n; long i; a[no]=i+a[n]; if(a[no]>longChain) { longChain = a[no]; startNo = no; } 当我这么做的时候 long a[] =new long[1000000]; long no=2,n; long i,longChain=1,startNo; a[no]=i+a[n]; if
long a[] =new long[1000000];
int no=2,n;
long i;
a[no]=i+a[n];
if(a[no]>longChain)
{
longChain = a[no];
startNo = no;
}
当我这么做的时候
long a[] =new long[1000000];
long no=2,n;
long i,longChain=1,startNo;
a[no]=i+a[n];
if(a[no]>longChain)
{
longChain = a[no];
startNo = no;
}
然后是精度损失
发现:长
必填项:int
有什么问题
我为上述问题编写的代码是ProjectEuler问题14
class P14
{
public static void main(String args[])
{
long a[] =new long[1000000];
long no=2,n;
long i,longChain=1,startNo;
a[1]=1;
while(no<1000000)
{
n=no;
i=0;
while(n>no-1)
{
if(n%2==0)
n=n/2;
else
n=3*n+1;
i++;
//System.out.println(n);
}
a[no]=i+a[n];
if (a[no] > longChain)
{
longChain=a[no];
startNo=no;
}
no++;
//System.out.println(no);
}
}
}
P14类
{
公共静态void main(字符串参数[])
{
长a[]=新长[1000000];
长no=2,n;
长i,长链=1,起始n;
a[1]=1;
while(nono-1)
{
如果(n%2==0)
n=n/2;
其他的
n=3*n+1;
i++;
//系统输出println(n);
}
a[no]=i+a[n];
if(a[no]>长链)
{
长链=a[否];
startNo=否;
}
否++;
//系统输出打印项次(否);
}
}
}
这是我的代码,上面的问题发生在哪里
答案:用[(int)n]替换[no]
a[n],a[(int)n]这可能是因为数组索引采用
int
作为索引。但是您的所有变量都是long
类型
a[no]
no
是一个long
a[no]
因此,使用long
作为数组索引是一种隐含的向下转换,可能会导致精度损失
因此,要么手动将其向下转换,要么将no
更改为int
编辑:(在问题的附加信息之后)
我不能100%确定这是否是原因:
n=3*n+1;
在索引中使用n
。但是n
一开始可能会变得相当大。因此,*3
可以使其大于数组的大小
您可能应该仔细检查您的算法。(我无法从代码本身看出这一点)您遇到的问题是无法在数组中存储所有可能计算的值。数字可以增长到2^31-1以上,并且会出现溢出 你所能做的就是
long n;
及
while(n>no-1 | | n>=a.length){
}
//当n
这样可以确保只查找数组中的缓存值。no和n变量必须是int,而不是long。数组不能按长索引。将代码更改为:
int no=2,n;
使代码可编译
ArrayIndexOutOfBoundsException是因为您编写的算法假设它是长的
此代码最终将导致n
变为负值:
n=3*n+1;
当你做整数运算时,很难理解为什么。稍微修改一下,使代码使用长算术并打印中间结果,可以准确地显示它何时变为负数以及如何变为负数:
while(n>no-1)
{
long newN = n;
if (n % 2 == 0) newN = newN / 2L;
else newN = 3L * newN + 1L;
if (newN > Integer.MAX_VALUE) System.out.println("about to fail");
//this is where the magic happens
n = (int)newN;
System.out.println("converted " + newN + " to " + n);
i++;
}
n
需要较长,因为它对于int可能太大。(如果使用int,它将溢出为负数,并导致ArrayIndexOutOfBoundsException。)
您必须将n
声明为long
,并在将其用作索引时将其强制转换为int(no
可以是int)
请花时间正确缩进代码,以使代码块格式化工作正常。现在读你的问题很枯燥。你不能把得到
ArrayIndexOutOfBounds
的代码描述为工作。您发布的代码甚至都没有编译过。问题无法以当前形式回答。@EJP没有精度错误,这就是我所说的工作,但您的权利,编辑我的Q“编译”与“工作”不一样。您的代码仍然无法编译。我建议您复制粘贴您的实际代码,不要尝试键入。@EJP我已经发布了您从未初始化过的源代码I
和n
。它们设置为什么?i,n在while循环中初始化,我发布了源代码是的,n将变得非常大,但在while循环退出之前,它将下降到1000 000以下。当你越界时,它应该告诉你你试图访问什么索引?谢谢,你是对的,n=3*n+1;是原因,因为n变为-ve,并退出while循环,然后尝试在-ve处存储值index@CoolEulerProject因此,您的数组索引超出了范围。所以你的算法是错误的。我发布了我的算法,它的ProjectEuler14问题谢谢,是的,数组索引随着n=n*3+1超出java数组容量而增加,所以我不得不用[(int)no]替换[no],用[(int)n]替换[n],因为n,no都很长。。。或者使用另一个保持n为整数的变量,然后使用ArrayIndexOutofBounds异常发生OK,我必须再使用一个变量,我想,我会在选中时更新OK,谢谢,我使用了long nL;循环之后,我将其存储在n中;我的程序正在运行!!!我刚刚写完一个例子,说明为什么n变成负值,以进一步解释发生了什么:)
a[no]=i+a[(int)n];