【问题标题】:In Java finding numbers that are both a Triangle Number and a Star Number在 Java 中查找既是三角形数又是星数的数
【发布时间】:2015-12-12 18:09:47
【问题描述】:

这是分配给我的问题:

所谓的“星数”,s,是一个由以下公式定义的数: s = 6n(n-1) + 1 其中 n 是星号的索引。 因此,前六个(即对于 n = 1、2、3、4、5 和 6)星号是:1、13、37、 73、121、181

相比之下,所谓的“三角形数”t 是从 1 到 n 的数字之和:t = 1 + 2 + … + (n-1) + n。 因此,前六个(即 n = 1、2、3、4、5 和 6)三角形数是:1、3、6、10、15、21

编写一个 Java 应用程序,生成一个包含所有 int 类型值的列表,这些值既是星号又是三角形数。

解决此问题时,您必须编写并使用至少一个函数(例如 isTriangeNumber()isStarNumber()determineTriangeNumber()determineStarNumber())。此外,您必须仅使用此处提供的公式来解决问题。

tl;dr:需要输出星号和三角号的值。

不幸的是,我只能在无限循环中获得输出值“1”的结果,即使我在 while 循环中递增 1。

public class TriangularStars {
    public static void main(String[] args) {

    int n=1;            
    int starNumber = starNumber(n);
    int triangleNumber = triangleNumber(n);

    while ((starNumber<Integer.MAX_VALUE)&&(n<=Integer.MAX_VALUE))
    {
        if ((starNumber==triangleNumber)&& (starNumber<Integer.MAX_VALUE))
                {
                    System.out.println(starNumber);
                }
        n++;
    }
  }


public static int starNumber( int n)
{
    int starNumber;
    starNumber= (((6*n)*(n-1))+1);
    return starNumber;

}
public static int triangleNumber( int n)
{
    int triangleNumber;
    triangleNumber =+ n;
    return triangleNumber;
}

}

【问题讨论】:

  • 您用于每种方法的 n 必须不同,因为一种方法的增长速度比另一种快得多。使用 starN 和 triangleN 并递增产生较小数字的“n”,直到它们匹配。

标签: java methods while-loop


【解决方案1】:

这是一个骷髅。自己完成剩下的:

要问自己的问题:

  1. 如何制作三角形数?
  2. 我如何知道某物是否是星号?
  3. 为什么我只需要继续直到三角形为负数?三角形怎么可能是负数?

祝你好运!

public class TriangularStars {
  private static final double ERROR = 1e-7;

  public static void main(String args[]) {
    int triangle = 0;
    for (int i = 0; triangle >= 0; i++) {
      triangle = determineTriangleNumber(i, triangle);
      if (isStarNumber(triangle)) {
        System.out.println(triangle);
      }
    }
  }

  public static boolean isStarNumber(int possibleStar) {
    double test = (possibleStar - 1) / 6.;
    int reduce = (int) (test + ERROR);
    if (Math.abs(test - reduce) > ERROR)
      return false;

    int sqrt = (int) (Math.sqrt(reduce) + ERROR);
    return reduce == sqrt * (sqrt + 1);
  }

  public static int determineTriangleNumber(int i, int previous) {
    return previous + i;
  }
}

输出:

1
253
49141
9533161
1849384153

【讨论】:

  • 我认为这个解决方案是不正确的,如果你只去 Math.sqrt(Integer.MAX_VALUE),你只测试三角形(46340),它的值为 1073720970。这只是〜1B,因此没有测试到2.14B(Integer.MAX_VALUE)的全部范围。这导致无法打印数字 1849384153,该数字既是星号也是三角形数。如果我犯了错误,请纠正我,但据我所知,我们只需要走到 Math.sqrt(Integer.MAX_VALUE) 的假设是不正确的
  • 你是对的,@AndrewB。它实际上需要是Math.sqrt(Integer.MAX_VALUE) * Math.sqrt(2),但有一种更简单的方法,我已将其编辑到我的答案中。
【解决方案2】:

您需要在循环内添加对starNumber()triangleNumber() 的新调用。您获得了初始值,但永远不会使用更新后的 n 值重新调用它们。

作为第一次剪辑,我会立即将这些调用放在 n++ 之后,所以

n++;
starNumber = starNumber(n);
triangleNumber = triangleNumber(n);
  }
}

【讨论】:

  • 当我这样做时,我只会得到 '1' 作为结果。当然它不再是一个无限循环(所以这是解决了一个问题),但我没有得到其他结果。
  • 请看我回答中的第三个问题。
【解决方案3】:

这里的问题是星号和三角形数的“N”不必相同。所以你可以在计算星数和三角形数时增加“n”,而不是继续增加三角形数,只要它小于当前的星数。本质上你需要维护两个变量“n”和“m”。

【讨论】:

    【解决方案4】:

    第一个问题是你只在循环外调用了一次starNumber() 方法。 (与triangleNumber() 相同。)

    第二个问题是除非Integer.MAX_VALUE 是星号,否则您的循环将永远运行。原因是 Java 数值运算会无声地溢出,所以如果你的下一个星号大于Integer.MAX_VALUE,结果就会回绕。您需要使用longs 来检测一个数字是否大于Integer.MAX_VALUE

    第三个问题是,即使将所有调用都放入循环中,它也只会显示共享相同n 值的星号/三角形号对。您需要并行有两个索引,一个用于星号,另一个用于三角形号,并根据哪个函数返回较小的数字来增加一个或另一个。所以沿着这些思路:

    while( starNumber and triangleNumber are both less than or equal to Integer.MAX_VALUE) {
       while( starNumber < triangleNumber ) {
         generate next starnumber;         
       }
       while( triangleNumber < starNumber ) {
         generate next triangle number;
       }
       if( starNumber == triangleNumber ) {
         we've found a matching pair
       }
    }
    

    第四个问题是你的triangleNumber()方法不对,我想知道它是怎么编译的。

    【讨论】:

    • 你的意思是对每个变量都使用 longs 而不是 int,然后在最后转换为 int 吗?
    • 您根本不需要将它们转换为整数。只需检查它们是否大于Integer.MAX_VALUE
    • 如何在while循环中生成嵌套starNumber?还是下一个三角形数?我应该再次调用该函数吗?
    • 比转换成long更好的是只检查它是否小于0。它不会从高正数跳过整个负数,一步变成低正数。所以如果你有一个负数,你知道你已经溢出,你知道如果你没有负数,你还没有溢出:添加 MAX + MAX 产生 -2。因此,如果它只是一次添加,您可以安全地测试是否为负以确定是否存在溢出。
    • 还能怎样?但如果我是你,我会选择@durron597 的答案。我的回答主要是关于为什么你的代码不起作用,这个答案让你知道如何以更好的方式编写它。
    【解决方案5】:

    我认为你的方法有缺陷。如果没有在该方法内部测试每个可能的星号,您将无法直接创建isStarNumber(n) 的方法。我会采取稍微不同的方法:预计算。

    首先,找出所有的三角形数:

    List<Integer> tris = new ArrayList<Integer>();
    for(int i = 2, t = 1; t > 0; i++) { // loop ends after integer overflow
        tris.add(t);
        t += i; // compute the next triangle value
    }
    

    我们可以对星号做同样的事情:

    考虑以下 -

    star(n) = 6*n*(n-1) + 1 = 6n^2 - 6n + 1
    
    therefore, by extension
    
    star(n + 1) = 6*(n+1)*n + 1 = 6n^2 + 6n +1
    
    and, star(n + 1) - star(n - 1), with some algebra, is 12n
    
    star(n+1) = star(n) + 12* n
    

    这导致我们得出以下公式

    List<Integer> stars = new ArrayList<Integer>();
    for(int i = 1, s = 1; s > 0; i++) {
        stars.add(s);
        s += (12 * i);
    }
    

    真正的问题是……我们真的需要搜索每个数字吗?答案是不!我们只需要搜索实际上是一个或另一个的数字。所以我们可以很容易地使用星星中的数字(其中 18k)并找到那些也是 tris 的数字!

    for(Integer star : stars) {
        if(tris.contains(star)) 
            System.out.println("Awesome! " + star + " is both star and tri!");
    }
    

    我希望这对你有意义。为了您自己的利益,不要盲目地将这些 sn-ps 移动到您的代码中。相反,要了解它为什么会这样做,在你不确定的地方提出问题。 (希望这不会在两个小时内到期!)

    祝你这次作业好运。

    这里有一些很棒的东西,它会返回前 4 个,但不会返回最后一个。我不知道为什么最后一个不会出来。玩得开心:

    class StarAndTri2 {
        public static void main(String...args) {
            final double q2 = Math.sqrt(2);
            out(1);
            int a = 1;
            for(int i = 1; a > 0; i++) {
                a += (12 * i);
                if(x((int)(Math.sqrt(a)*q2))==a)out(a);
            }
        }
        static int x(int q) { return (q*(q+1))/2; }
        static void out(int i) {System.out.println("found: " + i);}
    }
    

    【讨论】:

      猜你喜欢
      • 2019-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-16
      • 2010-09-27
      • 1970-01-01
      相关资源
      最近更新 更多