Java 按正弦波顺序打印数字

Java 按正弦波顺序打印数字,java,Java,背景: 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); st

背景:

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;
  }
}
我已经成功地编写了从0到2pi生成正弦波的代码。调整常量
xPrecision
yPrecision
,可以水平或垂直拉伸图形

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

我的查询:

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;
  }
}
我现在希望显示数字0到9,而不是星星。因此,最左边的星被0替换,第二个最左边的星被1替换,依此类推。当你达到9时,下一个数字又是零

我不知道该怎么做。我已经看过波浪模式,但它们是固定宽度的模式,而我的是可伸缩的

我能想到的唯一方法是将输出转换为二维字符数组,然后从左到右手动刮取
*
并用数字替换,然后打印。但是,如果
x/yPrecision
的值较大,则会极大地消耗内存

实现这一输出的最佳方式是什么


打印正弦波的代码:

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;
  }
}
类正弦{
静态最终双精度xPrecision=10.0;//(1/xPrecision)是x值的精度
静态最终双精度y=10.0;//(1/y精度)是y值的精度
静态最终整数PI=(整数)(3.1415*xPrecision);
静态最终int TPI=2*PI;//两次PI
静态final int HPI=PI/2;//半个PI
公共静态void main(字符串[]args){
双xd;
对于(int start=(int)(1*yPrecision),y=start;y>=-start;y--){
双x0=数学asin(y/y精度),
x1=精度不高(x0)的带X值,
x2=精度不高的带X值(x0+TPI/Xp精度),
x3=精度不高的带X值(PI/X精度-x0);
//用于调试
//系统输出打印项次(y+“”+x0+“”+x1+“”+x2+“”+x3);

对于(int x=0;x在循环中添加一个计数器,并在达到9时将其重置:

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

    if(x1 == xd || x2 == xd || x3 == xd) {
      System.out.print("" + counter);

      if (counter == 9) {
          counter = 0;
      }
    } else {
        System.out.print(" ");      
    }
}
for(int x=0,counter=0;x如果替换:

System.out.print("*");

它似乎几乎起作用了

               56                                              
           1        0                                          
         9            2                                        
        8              3                                       
      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      
                                       9              4        
                                        0            3         
                                          2        1           
                                              67               
也许进一步的调整可能会使它变得完美。

首先在内存中“绘制”图形,然后为其垂直点指定数字,并在单独的过程中打印它们

               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;
}
-
表示单元格带有
-1
,表示缺少的值。数组表示最左边的星号在第10行,下一个星号在第9行,然后是8、7、6,依此类推。星号11和12在第0行,位于顶部

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

第三个循环再次逐行遍历整个字段,当当前行与
行[]
数组中的值匹配时,打印预先指定的
位[]
数组中的值


这是我的解决方案,它基本上使用了四次循环中正弦的一半:

  • 从一半到0
  • 从0到一半
  • 从头到尾
  • 从头到尾
在每个循环中,只替换第一个星号

class sine {
    static final double xPrecision = 14.0; // (1/xPrecision) is the precision on x-values
    static final double yPrecision = 14.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;
        String str = "";
        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)
                    str += "*";
                else str += " ";
            }
            str += "\n";
        }
        String[] rows = str.split("\n");
        int half = (int)(1 * yPrecision);

        // we use this half in for loops, from half to 0, from 0 to half, from half to the end and from the end to the half, and replace only the first asterisk.
        int val = 0;
        for (int i = half; i >= 0; i--) {
            if (val == 10) val = 0;
            rows[i] = rows[i].replaceFirst("\\*", Integer.toString(val++));
        }
        for (int i = 0; i <= half; i++) {
            if (val == 10) val = 0;


            rows[i] = rows[i].replaceFirst("\\*", Integer.toString(val++));
        }
        for (int i = half + 1; i < rows.length; i++) {
            if (val == 10) val = 0;
            rows[i] = rows[i].replaceFirst("\\*", Integer.toString(val++));
        }
        for (int i = rows.length - 1; i >= half; i--) {
            if (val == 10) val = 0;
            rows[i] = rows[i].replaceFirst("\\*", Integer.toString(val++));
        }

        System.out.println(String.join("\n", rows));
    }

    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;
    }
}

用一种完全不同的方式去做会产生不同的画面,但会达到你的效果

本质上

for each y
  for each x
    calculate fx = sin(x)
    if fx == y print * else print space
它非常低效,因为它计算sin(x)
x*y
次,如果你填充一个矩阵,你可以计算sin(x)

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

private void sine() {
    for (double y = 1; y >= -1; y -= 1.0 / yPrecision) {
        int n = 0;
        for (double x = 0; x < 2.0 * Math.PI; x += 1.0 / xPrecision, n++) {
            double fx = Math.sin(x);
            boolean star = Math.round(fx*xPrecision) == Math.round(y*yPrecision);
            System.out.print((star ? ""+(n%10) : " "));
        }
        System.out.println();
    }
}

public void test(String[] args) {
    sine();
}

通过使用每行有一个点的事实(在每个坡度上),您可以在不使用额外内存或循环的情况下计算在每个点上显示哪个数字。下面是我的示例。请注意,我只检查了此示例仅在
xPrecision
yPrecision
为整数时有效。如果要使用双精度,则必须对其进行修改

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) Math.round(Math.PI * xPrecision);
    static final int TPI = 2 * PI; // twice PI
    static final int HPI = PI / 2; // half PI
    static final int cycles = 2; // prints from x=0 to 2*cycles*pi

    public static void main(String[] args) {
        double xd;
        int cycleoffset, cycleoffset2, topbottomoffset = 1;

        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), tmp;

            if (y == start) {
                if (x1 == x3) // when there is only one point at the top/bottom
                    topbottomoffset = 0;
                else if (x1 > x3) // swap x1 and x3
                {
                    tmp = x1;
                    x1 = x3;
                    x3 = tmp;
                }
            } else if (y == -start) {
                // I don't think this is needed, but just for safety make sure there is only one point on the bottom if there was only one point at the top
                if (topbottomoffset == 0)
                    x2 = x3;
                else if (x2 < x3) // swap x2 and x3
                {
                    tmp = x2;
                    x2 = x3;
                    x3 = tmp;
                }
            }

            cycleoffset = (int) (4 * yPrecision + 2 * topbottomoffset);
            cycleoffset2 = -cycleoffset;

            int start1 = topbottomoffset + 2 * (int) yPrecision, start2 = 2 * topbottomoffset + 4 * (int) yPrecision;

            for (int x = 0, lim = cycles * TPI; x <= lim; x++) {
                xd = ((x % TPI) / xPrecision);
                if (x % TPI == 0)
                    cycleoffset2 += cycleoffset;

                // x = 0 to pi/2
                if (x1 == xd)
                    System.out.print((cycleoffset2 + y) % 10);
                // x = 3pi/2 to 2pi
                else if (x2 == xd)
                    System.out.print((cycleoffset2 + start2 + y) % 10);
                // x = pi/2 to 3pi/2
                else if (x3 == xd)
                    System.out.print((cycleoffset2 + start1 - y) % 10);
                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;
    }
}
类正弦{
静态最终双精度xPrecision=10.0;//(1/xPrecision)是x值的精度
静态最终双精度y=10.0;//(1/y精度)是y值的精度
静态最终整数PI=(int)Math.round(Math.PI*xPrecision);
静态最终int TPI=2*PI;//两次PI
静态final int HPI=PI/2;//半个PI
静态最终整数周期=2;//从x=0打印到2*cycles*pi
公共静态void main(字符串[]args){
双xd;
int cycleoffset,cycleoffset2,topbottomoffset=1;
对于(int start=(int)(1*yPrecision),y=start;y>=-start;y--){
double x0=数学asin(y/y精度),x1=带精度的X值(x0),
x2=精度不高的带X值(x0+TPI/Xp精度),
x3=带精度的带X值(PI/X精度-x0),tmp;
如果(y==开始){
if(x1==x3)//当顶部/底部只有一个点时
topbottomoffset=0;
else if(x1>x3)//交换x1和x3
{
tmp=x1;
x1=x3;
x3=tmp;
}
}否则如果(y==-开始){
//我不认为这是必要的,但为了安全起见,如果顶部只有一个点,请确保底部只有一个点
如果(topbottomoffset==0)
x2=x3;
else if(x2
。发生这种情况是因为当
y=yPrecision
时,我们将
Math.as
             345678                                            
           12      901                                         
         90           2                                        
        8              34                                      
      67                 5                                     
     5                    6                                    
    4                      7                                   
   3                        8                                  
  2                          9                                 
 1                            0                                
0                              1                               
                                2                             2
                                 3                           1 
                                  4                         0  
                                   56                      9   
                                     7                    8    
                                      8                 67     
                                       9               5       
                                        01           34        
                                          23       12          
                                            4567890            
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) Math.round(Math.PI * xPrecision);
    static final int TPI = 2 * PI; // twice PI
    static final int HPI = PI / 2; // half PI
    static final int cycles = 2; // prints from x=0 to 2*cycles*pi

    public static void main(String[] args) {
        double xd;
        int cycleoffset, cycleoffset2, topbottomoffset = 1;

        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), tmp;

            if (y == start) {
                if (x1 == x3) // when there is only one point at the top/bottom
                    topbottomoffset = 0;
                else if (x1 > x3) // swap x1 and x3
                {
                    tmp = x1;
                    x1 = x3;
                    x3 = tmp;
                }
            } else if (y == -start) {
                // I don't think this is needed, but just for safety make sure there is only one point on the bottom if there was only one point at the top
                if (topbottomoffset == 0)
                    x2 = x3;
                else if (x2 < x3) // swap x2 and x3
                {
                    tmp = x2;
                    x2 = x3;
                    x3 = tmp;
                }
            }

            cycleoffset = (int) (4 * yPrecision + 2 * topbottomoffset);
            cycleoffset2 = -cycleoffset;

            int start1 = topbottomoffset + 2 * (int) yPrecision, start2 = 2 * topbottomoffset + 4 * (int) yPrecision;

            for (int x = 0, lim = cycles * TPI; x <= lim; x++) {
                xd = ((x % TPI) / xPrecision);
                if (x % TPI == 0)
                    cycleoffset2 += cycleoffset;

                // x = 0 to pi/2
                if (x1 == xd)
                    System.out.print((cycleoffset2 + y) % 10);
                // x = 3pi/2 to 2pi
                else if (x2 == xd)
                    System.out.print((cycleoffset2 + start2 + y) % 10);
                // x = pi/2 to 3pi/2
                else if (x3 == xd)
                    System.out.print((cycleoffset2 + start1 - y) % 10);
                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;
    }
}
                                            3030              
                                          28    28            
                                        26        26          

                                      22            22        

                                    18                18      


                                  12                    12    


                                06                        06  


00                            00                            00


  06                        06                                


    12                    12                                  


      18                18                                    

        22            22                                      

          26        26                                        
            28    28                                          
              3030                                            
import static java.lang.Math.sin;
import static java.lang.Math.PI;
import static java.lang.Math.abs;

public class Sine {

    static final Integer points = 30; // points on x and y axis

    public static void main(String[] args) {

        // contains graph points
        Boolean[][] graph = new Boolean[points + 1][points + 1];

        for (Double x = 0.0; x <= points; x++) {
            // x axis pi value
            Double pi = (x / points) * 2 * PI;
            // sin(x) plot for x
            Integer sinx = (int) Math.round((sin(pi) * points / 2) + points / 2);
            graph[sinx][x.intValue()] = true;
        }

        for (Integer i = 0; i <= points; i++) {
            for (Integer j = 0; j <= points; j++) {

                // space characters on x axis
                Integer pt = (int) Math.floor(Math.log10(points) + 1);
                String space = String.format("%" + pt + "s", " ");

                // padding for p
                String p = String.format("%0" + (pt) + "d", abs(i - points / 2) * 2);

                System.out.print(graph[i][j] != null ? p : space);
            }
            System.out.println();
        }

    }

}