将正弦波打印到控制台
Printing a Sine Wave to the Console
我正在开发一个 Java 程序,可以将正弦波打印到控制台。这是我到目前为止写的:
int num = 7;
for (double y = 2; y >= 0; y-=0.2) {
for (double x = 0; x <= num; x+=0.2) {
if ( ((0.1+x) >= Math.asin((double)y-1)) && (((double)x-0.1) <= Math.asin((double)y-1)) )
System.out.print('*');
else
System.out.print(' ');
}
System.out.println();
}
本质上,该程序将每行中的每个字符视为坐标平面上的 0.2 x 0.2 区域。如果正弦函数穿过这个区域,屏幕上会打印一个星号。否则,将打印 space。
当 运行 时,将打印到控制台:
*
*
*
*
*
*
谁能告诉我为什么我的程序在打印第一四分之一波后停止了?
编辑:糟糕,浏览代码有点太快了。这是错误的。
好吧,您将 num
设置为 7,然后在循环中将 x 从 0 取到 num-1
,因此您只循环 7 列。增加 num 并且您的图形应该添加额外的列。如果您希望图表扩展到负数,您也必须增加循环的 y 值的范围。
但是,您的算法效率极低。您正在为图表上的每个正方形计算两次 asin(y-1)
,而您真正需要做的只是为每一列计算一次 sin(x)
。为什么不直接用预先计算的正弦值填充一个数组,然后在绘制图形时参考该数组? (当然,我意识到,在现代计算机上,它的速度足够快,实际上无论哪种方式都无关紧要。)
问题似乎是由您的 if 语句的条件引起的,它的计算结果几乎总是 false
。您应该检查条件表达式背后的微积分。我发现增加 num
在这里并没有真正帮助。
也许您应该打印另一个字符而不是空格,例如将 System.out.print(' ');
替换为 System.out.print('_');
。这样您就可以弄清楚为什么您的程序会这样运行。修改您的算法也可能有所帮助。
它只打印正弦波的第一季度的原因是因为指定的 range of Math.asin
:
Returns the arc sine of a value; the returned angle is in the range -pi/2 through pi/2.
一旦 x
超过 Math.PI / 2
,则 if
语句的条件将始终为 false
.
您可以利用
sin(π - x) = sin(x)
和
sin(2π - x) = -sin(x)
包括更多条件。 (为了清楚起见,我还删除了对 double
的不必要的强制转换。)
if ( (0.1+x >= Math.asin(y-1)) && (x-0.1 <= Math.asin(y-1)) ||
(0.1+x >= Math.PI - Math.asin(y-1)) && (x-0.1 <= Math.PI - Math.asin(y-1))
(2*Math.PI -(0.1 + x) <= -Math.asin(y-1)) && (2*Math.PI -(x-0.1) >= -Math.asin(y-1)) )
输出:
*
* *
* *
* * *
* * *
* * *
* *
* *
* *
* *
*
谢谢大家的帮助!根据@dasblinkenlight 的建议使用 sin 而不是 asin,我找到了一个非常简单的解决方案:
int num = 7;
for (double y = 1; y >= -1; y-=0.2) {
for (double x = 0; x <= num; x+=0.2) {
double sin = Math.sin(x);
if ( (0.1+y) >= sin && (y-0.1) <= sin )
System.out.print('*');
else
System.out.print(' ');
}
System.out.println();
}
这会将其打印到控制台:
*****
** *
* **
* * **
* * *
* * *
* *
* *
* *
** **
****
我正在开发一个 Java 程序,可以将正弦波打印到控制台。这是我到目前为止写的:
int num = 7;
for (double y = 2; y >= 0; y-=0.2) {
for (double x = 0; x <= num; x+=0.2) {
if ( ((0.1+x) >= Math.asin((double)y-1)) && (((double)x-0.1) <= Math.asin((double)y-1)) )
System.out.print('*');
else
System.out.print(' ');
}
System.out.println();
}
本质上,该程序将每行中的每个字符视为坐标平面上的 0.2 x 0.2 区域。如果正弦函数穿过这个区域,屏幕上会打印一个星号。否则,将打印 space。 当 运行 时,将打印到控制台:
*
*
*
*
*
*
谁能告诉我为什么我的程序在打印第一四分之一波后停止了?
编辑:糟糕,浏览代码有点太快了。这是错误的。
好吧,您将 num
设置为 7,然后在循环中将 x 从 0 取到 num-1
,因此您只循环 7 列。增加 num 并且您的图形应该添加额外的列。如果您希望图表扩展到负数,您也必须增加循环的 y 值的范围。
但是,您的算法效率极低。您正在为图表上的每个正方形计算两次 asin(y-1)
,而您真正需要做的只是为每一列计算一次 sin(x)
。为什么不直接用预先计算的正弦值填充一个数组,然后在绘制图形时参考该数组? (当然,我意识到,在现代计算机上,它的速度足够快,实际上无论哪种方式都无关紧要。)
问题似乎是由您的 if 语句的条件引起的,它的计算结果几乎总是 false
。您应该检查条件表达式背后的微积分。我发现增加 num
在这里并没有真正帮助。
也许您应该打印另一个字符而不是空格,例如将 System.out.print(' ');
替换为 System.out.print('_');
。这样您就可以弄清楚为什么您的程序会这样运行。修改您的算法也可能有所帮助。
它只打印正弦波的第一季度的原因是因为指定的 range of Math.asin
:
Returns the arc sine of a value; the returned angle is in the range -pi/2 through pi/2.
一旦 x
超过 Math.PI / 2
,则 if
语句的条件将始终为 false
.
您可以利用
sin(π - x) = sin(x)
和
sin(2π - x) = -sin(x)
包括更多条件。 (为了清楚起见,我还删除了对 double
的不必要的强制转换。)
if ( (0.1+x >= Math.asin(y-1)) && (x-0.1 <= Math.asin(y-1)) ||
(0.1+x >= Math.PI - Math.asin(y-1)) && (x-0.1 <= Math.PI - Math.asin(y-1))
(2*Math.PI -(0.1 + x) <= -Math.asin(y-1)) && (2*Math.PI -(x-0.1) >= -Math.asin(y-1)) )
输出:
*
* *
* *
* * *
* * *
* * *
* *
* *
* *
* *
*
谢谢大家的帮助!根据@dasblinkenlight 的建议使用 sin 而不是 asin,我找到了一个非常简单的解决方案:
int num = 7;
for (double y = 1; y >= -1; y-=0.2) {
for (double x = 0; x <= num; x+=0.2) {
double sin = Math.sin(x);
if ( (0.1+y) >= sin && (y-0.1) <= sin )
System.out.print('*');
else
System.out.print(' ');
}
System.out.println();
}
这会将其打印到控制台:
*****
** *
* **
* * **
* * *
* * *
* *
* *
* *
** **
****