微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

尽管使用 Long 原始类型和 Big Integer 的大型斐波那契序列的整数溢出

如何解决尽管使用 Long 原始类型和 Big Integer 的大型斐波那契序列的整数溢出

我正在编写一个程序来打印第 n 个斐波那契数

方法 FIBBO(int n) 使用 long 和 BigInteger 类型的组合来存储斐波那契运算的结果。当认为prev+next>Long.MAX_VALUE使用big_flag时,该方法假设切换到使用BigInteger。然而,这个程序只有在我在第二个循环中使用 Integer.MAX_VALUE 时才有效。

当我使用 Long.MAX_VALUE 时,无论 n 的值有多大,现在都不会触发 big_flag 的第二个循环,并且我只得到垃圾值。我不明白为什么当我使用 Long.MAX_VALUE 时我的溢出逻辑永远不会被激活。

import java.util.*;
import java.math.*;

public class fibbo_iteration{
    public static void main(String argss[])
    {
        BigInteger result;                      
        Scanner input=new Scanner(system.in);
        int n=0;                                
        System.out.println("Enter number of terms for fibbonacci sequence");
        n=input.nextInt();
        if(n<0){
            System.out.println("Fibbonaci sequence cannot be generated for the entered negative value");
            System.exit(1);
        }
        
        result=fibbo_iteration.FIBBO(n);        //call
        System.out.println(result.toString());  
    }
    static BigInteger FIBBO(int n)
    {
        // variables
        long sum=0L,prev=0L,next=1L;
        BigInteger big_prev=new BigInteger("0"),big_next=new BigInteger("0"),big_sum=new BigInteger("0");
        boolean big_flag=false;
    
            for(int i=0;i<n;i++){
                if(big_flag){
                    // System.out.println(big_sum.toString()); to use when printing a series upto n 
                    big_prev=big_next;
                    big_next=big_sum;
                    big_sum=big_prev.add(big_next);
                }
                else if(prev+next>Long.MAX_VALUE){   // ***The program works abolutely correct if i replace LONG.MAX_VALUE with Integer.MAX_Value***
                    big_prev=new BigInteger(String.valueOf(prev));
                    big_next=new BigInteger(String.valueOf(next));
                    big_sum=big_prev.add(big_next);
                    big_flag=true;  // this is supposed to signal the switch to BigInteger
                    System.out.println("Value exceeds Long");
                }   
                else{
                    if(i==1){   // this if block accomodates the eccentricity of starting the fibbonaci sequence  
                        sum=1L;
                        continue;
                    }   
                sum=prev+next;
                prev=next;
                next=sum;
                System.out.println(sum);
                }
            }
        return big_flag==true?big_sum:new BigInteger(String.valueOf(sum));
    }
}   

解决方法

Long 的最大值实际上是该类型的最大值。上面的任何计算都会给你......结果你显然没有预料到。 prev+next>Long.MAX_VALUE 类型的支票是无稽之谈。它永远不会是真实的。

应该使您的程序工作的一些更改是:prev > Long.MAX_VALUE - next

如果你想更详细地理解,你可以使用我写的比较和调试,在 if 块中放置一个断点。尝试查看 prev+next 的值。看看它是如何变成负面的。这是因为您达到了 long 无法存储的值。

,

使用Math.addExact(long,long)。使用 try-catch 环绕并在抛出异常时切换到 BigInteger。

    try
    {
        sum=Math.addExact(prev,next);
        prev=next;
        next=sum;
        System.out.println(sum);
    }
    catch(ArithmeticException overflow)//Out of range
    {
        big_prev=new BigInteger(String.valueOf(prev));
        big_next=new BigInteger(String.valueOf(next));
        big_sum=big_prev.add(big_next);
        big_flag=true;  // this is supposed to signal the switch to BigInteger
        System.out.println("Value exceeds Long");
    }

此代码段应放置在对应于 elseif(big_flag) 块中。

另见Integer Overflow

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。