我有一个简单的问题.. 我有这段代码:
program wtf;
var i:integer;
begin
for i:=1 to 20 do
if sqrt(i)*sqrt(i)<>i then writeln(i);
readln
end.
... 它通过循环20次,数字从1到20,它检查平方根乘以买相同数的平方根是否等于该数。 如果我们使用数学规则,这个程序应该永远不会有任何输出,但.... 我明白了:
2
3
5
6
7
8
10
12
13
15
18
19
20
可以用sombody来解释发生了什么事吗?
答案 0 :(得分:2)
这是因为精确。不是完美正方形的数字的平方根将给出无理数,使用浮点运算无法在内存中正确表示。
相反,数字会在某些数字后被截断(以二进制形式显示,但概念与十进制相同)。
这个数字现在非常接近原始数字的平方根,但并不完全。平方将产生一个非常接近原始数字的数字,但不完全。
想象一下,2的平方根是1.4142135623........(etc.)
,但由于记忆原因它被切断为1.414213
。 1.414213
* 1.414213
= 1.99999840937
而非2
。
然而,4
的平方根是2
,这可以完全存储在内存中,而不会在几个小数位后被切断。然后,当您执行2
* 2
时,您确实会得到4
。
有时这个数字可能会被切断,但是在平方时它仍然足够接近以产生原始值。这就是11
未显示的原因。
答案 1 :(得分:1)
sqrt
生成浮点数。在计算机上使用浮动时,您无法比较值并期望绝对相等。您必须使用阈值差异比较。浮点数不用于计算事物,它们用于衡量事物,(计算事物,使用整数)。没有两个测量(即使在现实世界中)值完全相同。他们只是“足够接近”。
在计算机上,无法表示每个可能的实数。因此,每个计算值由可能数字集合中的“最接近”数字表示(对于该数据类型),可以在计算机上表示。这意味着它有点不正确,因此经过一些计算后,它将不符合完美的相等比较。