java - 按正弦波顺序打印数字

标签 java

背景:

我已经成功编写了生成 0 到 2pi 正弦波的代码。调整常量 xPrecisionyPrecision,您可以水平或垂直拉伸(stretch)图形。

xPrecision = yPrecision = 10 时,我获得了这个整洁的输出(在 Eclipse 中):

enter image description here

我的查询:

我现在希望显示数字 0 到 9 而不是星星。因此,最左边的星星被 0 替换,第二个最左边的星星被 1 替换,依此类推。当您达到 9 时,下一位数字再次为零。

我不知道该怎么做。我看过波浪模式 like this ,但它们是固定宽度的图案,而我的图案是可缩放的。

我能想到的唯一方法是将我的输出转换为二维字符数组,然后从左到右手动抓取 *,并用数字替换它们,然后打印它。但是,当 x/yPrecision 的值较大时,这会非常消耗内存。

What is the most optimized way to achieve this output?


打印正弦波的代码:

class sine {
  static final double xPrecision = 10.0; // (1/xPrecision) is the precision on x-values
  static final double yPrecision = 10.0; // (1/yPrecision) is the precision on y-values
  static final int PI = (int) (3.1415 * xPrecision);
  static final int TPI = 2 * PI; // twice PI
  static final int HPI = PI / 2; // half PI

  public static void main(String[] args) {
    double xd;

    for(int start = (int) (1 * yPrecision), y = start; y >= -start; y--){       
      double x0 = Math.asin(y / yPrecision),
            x1 = bringXValueWithinPrecision(x0),
            x2 = bringXValueWithinPrecision(x0 + TPI / xPrecision),
            x3 = bringXValueWithinPrecision(PI/xPrecision - x0);

      // for debug
      //System.out.println(y + " " + x0 + " " + x1 + " " + x2 + " " + x3);

      for(int x = 0; x <= TPI; x++){
        xd = (x / xPrecision);

        if(x1 == xd || x2 == xd || x3 == xd)
          System.out.print("*");
        else System.out.print(" ");      
      }

      System.out.println();
    }
  }

  public static double bringXValueWithinPrecision(double num){
      // obviously num has 16 floating points
      // we need to get num within our precision
      return Math.round(num * xPrecision) / xPrecision;
  }
}

最佳答案

首先在内存中“绘制”图形,然后将数字分配给其垂直点,并在单独的 pass 中打印它们。

               01                                              
           9        2                                          
         8            3                                        
        7              4                                       
      6                  5                                     
     5                    6                                    
    4                      7                                   
   3                        8                                  
  2                          9                                 
 1                            0                                
0                              1                              2
                                2                            1 
                                 3                          0  
                                  4                        9   
                                   5                      8    
                                    6                    7     
                                     7                  6      
                                       8              5        
                                        9            4         
                                          0        3           
                                              12               

请参阅代码中的注释以了解其工作原理:

static final double xPrecision = 10.0; // (1/xPrecision) is the precision on x-values
static final double yPrecision = 10.0; // (1/yPrecision) is the precision on y-values
static final int PI = (int) (3.1415 * xPrecision);
static final int TPI = 2 * PI; // twice PI
static final int HPI = PI / 2; // half PI

public static void main(String[] args) {
    // This part is the same as OP's code, except that instead of printing '*'
    // it stores the corresponding row number in the array of rows
    double xd;
    int[] row = new int[100];
    Arrays.fill(row, -1);
    int r = 0;
    int maxc = 0; // Mark the rightmost column of all iterations
    for(int start = (int) (1 * yPrecision), y = start; y >= -start; y--){       
      double x0 = Math.asin(y / yPrecision),
            x1 = bringXValueWithinPrecision(x0),
            x2 = bringXValueWithinPrecision(x0 + TPI / xPrecision),
            x3 = bringXValueWithinPrecision(PI/xPrecision - x0);
      int c = 0;
      for(int x = 0; x <= TPI; x++, c++){
        xd = (x / xPrecision);
        // This is where the asterisk used to go
        if(x1 == xd || x2 == xd || x3 == xd)
          row[c] = r;
      }
      maxc = Math.max(c, maxc);
      r++;
    }
    // Walk the assigned rows, and give each one a consecutive digit
    int[] digit = new int[100];
    int current = 0;
    for (int i = 0 ; i != 100 ; i++) {
        if (row[i] != -1) {
            digit[i] = (current++) % 10;
        }
    }
    // Now walk the rows again, this time printing the pre-assigned digits
    for (int i = 0 ; i != r ; i++) {
        for (int c = 0 ; c != maxc ; c++) {
            if (row[c] == i) {
                System.out.print(digit[c]);
            } else {
                System.out.print(' ');
            }
        }
        System.out.println();
    }
}

public static double bringXValueWithinPrecision(double num){
      // obviously num has 16 floating points
      // we need to get num within our precision
      return Math.round(num * xPrecision) / xPrecision;
}

代码的第一部分填充row[i] 数组,其中包含i 列中星号的行。 row[] 数组中的前几个数字如下所示:

10 9 8 7 6 5 4 - 3 2 - 1 - - - 0 0 - - - 1 - 2 3 - 4 5 6 7 8 9 10

- 表示带有-1 的单元格,表示缺失值。该数组表明最左边的星号位于第 10 行,下一个星号位于第 9 行,然后是第 8、7、6 行,依此类推。星号 11 和 12 位于顶部的第 0 行。

第二个循环遍历,跳过-1,并将连续数字分配给所有非负数位置。

第三个循环再次逐行遍历整个字段,当当前行与 row[] 中的值匹配时,打印来自预先分配的 digit[] 数组的值 数组。

Demo.

关于java - 按正弦波顺序打印数字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48208510/

相关文章:

Window 上的 Java Swing pack() 未最大化它,如何避免这种情况?

java - 在 swing-java 中,Graphics 实例从何而来?

java - 如何在 Java 中将列表项保存在磁盘而不是内存上

java - 单元测试 OSGi 组件

java - 反射 - 将接口(interface)实现为参数的类

java - R调用java中文编码乱码

java - Android 上连续按 2 个按键?

java - 将单词对象添加到 ArrayList 中

java - Lombok toBuilder() 方法是否创建字段的深拷贝

java - 禁用库的日志输出