【问题标题】:What's causing Java (hailstone sequence) to crash in my program是什么导致 Java(冰雹序列)在我的程序中崩溃
【发布时间】:2012-08-29 13:03:47
【问题描述】:

我做了一个程序来执行(通常称为)冰雹序列,该程序基本上是这样做的:

创建一个int(值)并为其分配一个值。

如果 int 是偶数,则除以二。

如果 int 是奇数,则将其乘以 3 并加 1。继续这个过程,直到 n 等于 1。

似乎大多数数字都可以正常工作,但是这个数字 99888769,应用程序挂在一个负整数上。为什么会这样?,他们说没有人能够证明它停止了,我没想到我已经解决了这个问题。但是知道为什么我的应用程序停止会很有趣。 -

    private void hailStoneSequence(){
    int value = 99888769;
    int i = 0;
    boolean trueOrFalse = isOddOrEven (value);
    while (value != 1){
        while (trueOrFalse == true && value != 1){
            i++;
            int previousValue = value;
            value = value / 2;
            println( previousValue +" is even, so I take half: "+value);
            trueOrFalse = isOddOrEven (value); // returning true or false, and inserting the newly divided number. So that it breaks loop when nescesary.
        }
            while (trueOrFalse == false && value != 1){
                i++;
                int previousValue = value;
                value = (value * 3) + 1;
                println (previousValue +" is odd, so I make 3n+1: "+value); 
                trueOrFalse = isOddOrEven (value);  
            }
                }       
    println ("\n\nThe process took "+i+" to reach "+value);
}

private boolean isOddOrEven(int value){
    /*
     * Takes an value and returns true, if that number is even.
     * Else it returns false.
     */
    if (value % 2 != 0){
    return false;
    }else{
        return true;
    }
}

}

【问题讨论】:

  • 作为一个小提示:你的 isOddOrEven() 方法和 trueOrFalse 变量有奇怪的名字。将布尔函数和布尔变量命名为断言肯定形式的短语要好得多。例如,如果您的变量名为 isOdd,那么当值为奇数时,isOdd 将是 true,如果值为偶数,isOdd 将是 false。这使得阅读代码变得更加容易。
  • 注意...我明白你的意思,它们不是很可读。

标签: java math integer sequence


【解决方案1】:

随着您不断增加ints,它们最终会(以一种看似令人吃惊的行为)变为负数,因为您超过了 int 类型的最大值 (2^31-1),即您最终会更改用于存储数字符号的位(int 的二进制表示)。请改用long

【讨论】:

  • 正确!将 int's 更改为 long... 它不会崩溃,但 - 有点遗憾我没有解决这个古老的数学难题。
  • 嘿,是的,人们已经尝试了一段时间,所以不要难过 :-)
【解决方案2】:

你实际上选择了一个有趣的起始号码。从那里开始,您最终会得到数字:768879215。将其乘以 3 并加 1 会超过 int 可以存储的最大值 (2^31-1),因此它“溢出”为负数。冰雹序列对于负数并不总是收敛到 1,实际上在这种情况下它会永远重复以下序列:

-122
-61
-182
-91
-272
-136
-68
-34
-17
-50
-25
-74
-37
-110
-55
-164
-82
-41
-122

您可以改用long,您的代码最多可以工作到 (2^63-1),或者使用BigInteger 类,它可以用于任何数字。

【讨论】:

    【解决方案3】:

    因为您的整数溢出。改用“long”,您的代码将运行良好,至少在您的序列甚至超出 longs 范围之前。

    【讨论】:

    • 或使用 BigInteger 并始终获得准确的结果(或没有结果)。
    【解决方案4】:

    你的逻辑对我来说似乎很复杂。重新编写您的代码以使其更清晰,您应该能够看到发生了什么:

    public class HailStoneSequence {
    
        public void sequence() {
            int value = 99888769;
            int i = 0;
            while (value != 1) {
                int previousValue = value;
                if (value % 2 == 0) {
                    value = value / 2;
                    System.out.println(previousValue + " is even, so I take half: " + value);
                } else {
                    value = (value * 3) + 1;
                    System.out.println(previousValue + " is odd, so I make 3n+1: " + value);
                }
            }
    
            i++;
            System.out.println("\n\nThe process took " + i + " to reach " + value);
        }
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            HailStoneSequence instance = new HailStoneSequence();
            instance.sequence();
        }
    
    }
    

    现在,如果您运行它,您应该会看到它不会停止,而是会重复。因此,它产生了一个无限的系列......

    【讨论】:

      【解决方案5】:

      您的初始种子值导致您达到“int”数据类型的整数溢出。这会导致负值的重复序列。您可以更改为使用“长”数据类型,也可以从不同(较小的)种子值开始。

      public class HailStoneSequence 
      {
      
          public static void processSequence()
          {
              long value = 99888769;   // works due to larger type range
              // int value = 99888769; // causes negative repeating sequence
              // int value = 81;       // works with smaller seed
              int i=0;
      
              while(value != 1)
              {
                  System.out.println("The value is:" + value);
                  i++;
                  if(value % 2 == 0)
                  {
                      value /= 2;
                  }
                  else
                  {
                      value = value * 3 + 1;
                  }
              }
              System.out.println("The process took " + i + " iterations to solve.");
          }
      
          public static void main(String[] args) 
          {
              System.out.println("Begin Hailstorm:");
              HailStoneSequence.processSequence();
              System.out.println("End Hailstorm:");
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-11
        • 1970-01-01
        • 2012-07-13
        • 2018-10-15
        • 2019-07-08
        • 1970-01-01
        相关资源
        最近更新 更多