我目前正在为我的离散结构课程进行练习,分配如下:
“下面的算法表示尝试以0.1的步长打印出一个从0.1到10的数字的多维数据集的表。请解释如果在计算机上实现该算法可能会出现的问题:
x = 0.0
Repeat
x = x + 0.1
x_cubed = x^3
Output x, x_cubed
until x = 10.0
这是伪代码,因此我认为错误与语法无关。我重写了Java中的代码并运行了它。如果我将(x!= 10.0)作为条件,该程序将永不停止,因为出于某些原因0.2 + 0.1会导致0.30000000000000004,这使x永远不会精确变为10.0。但是,我不知道这是否是教授正在寻找的问题,因为它可能是Eclipse或Java问题。
有人可以帮我做这个练习吗?谢谢!
问题是,在大多数情况下,比较浮点数是否等于(until x = 10.0
)将为not work as one would expect。在您的特定情况下,一种解决方案是为循环使用一个整数,并在需要时使用另一个浮点数。
int i = 1
float x = 0.0
Repeat
x = x + 0.1
x_cubed = x^3
Output x, x_cubed
until i = 10
Dialecticus正确:比较计算得出的浮点数是否相等是危险的。由于某些数字不能以二为底完美地表示(例如0.1),因此这些数字只能近似正确。
您可以按照他的建议使用整数,但是我要作进一步的调整:与其计算x [n + 1] = x [n] + dx,不如考虑计算x [n + 1] = dx * i [n +1]。换句话说,不要使用重复加法(随着时间的流逝可能会累积大量错误);取而代之的是,根据迭代的整数和浮点步长(在这种情况下为0.1),在每次迭代中计算x de novo的值。这将不会以相同的方式随时间累积错误。我鼓励您通过比较在每个步骤中通过重复加法与直接乘法获得的百万分之一的值来尝试此操作。
上述问题可以通过将浮点值四舍五入到所需的小数点(在这种情况下为1个小数)来解决。
Math.round(floating_point_number * 100)/ 100.00会将数字四舍五入为两位小数。
Math.round(floating_point_number * 10)/ 10.00将四舍五入到小数点后1位。
这里是使用四舍五入输入值的有效解决方案:
// File name: Cube.java
public class Cube {
public static void main(String[] args) {
// Find cubes of numbers from 0.1 till 10, with increments of 0.1
for (double x = 0.1; x <= 10.00; x += 0.1) {
x = (Math.round(x * 10) / 10.00);
System.out.println("Cube of " + x + " = " + Math.pow(x, 3));
}
}
}
输出:
$ javac Cube.java
$ java Cube
Cube of 0.1 = 0.0010000000000000002
Cube of 0.2 = 0.008000000000000002
Cube of 0.3 = 0.026999999999999996
Cube of 0.4 = 0.06400000000000002
Cube of 0.5 = 0.125
Cube of 0.6 = 0.21599999999999997
Cube of 0.7 = 0.3429999999999999
Cube of 0.8 = 0.5120000000000001
Cube of 0.9 = 0.7290000000000001
Cube of 1.0 = 1.0
Cube of 1.1 = 1.3310000000000004
Cube of 1.2 = 1.7279999999999998
...
...
Cube of 9.8 = 941.1920000000002
Cube of 9.9 = 970.2990000000001
Cube of 10.0 = 1000.0
$