这里的问题是你正在使用float
多变的 (gap
),但您将其与double
持续的 (0.00002
)。常数是double
因为除非另有说明,C 中的浮点常量都是 double 的。
一个根本问题是数量0.00002
都不能代表float
or double
。 (它根本无法用二进制浮点数表示,因为它的二进制扩展是无限长的,就像 ⅓ 的十进制扩展一样。)所以当你写0.00002
在程序中,C 编译器将其替换为double
值非常接近0.00002
。同样,当scanf
读取号码0.00002
into a float
变量,它替代了float
值非常接近0.00002
. Since double
数字的位数多于floats
, the double
值更接近于0.00002
比float
value.
当您比较两个具有不同精度的浮点值时,编译器会将精度较低的值转换为精度较高的完全相同的值。 (该组值表示为double
是表示为的值集的超集float
,所以总是可以找到一个double
其值与 a 的值相同float
.) 这就是当发生的情况gap < 0.00002
被执行:gap
被转换为double
相同的值,并且与 double 相比(接近)0.00002
。由于这两个值实际上都略小于 0.00002,并且double
越接近,则float
小于double
.
您可以通过多种方式解决此问题。首先,您可以通过以下方式避免转换:gap
a double
并改变scanf
格式化为%lf
,或者通过比较gap
to a float
:
while (gap < 0.00002F || gap > 0.99999F) {
但这并不完全正确,原因有几个。首先,实际上不能保证 C 编译器完成的浮点转换与标准库完成的转换相同(scanf
),并且该标准允许编译器使用“以实现定义的方式选择的最接近的可表示值,或者紧邻最近可表示值的较大或较小的可表示值”。 (它没有详细说明哪个值scanf
产生其中之一,但建议它是最接近的可表示值。)碰巧的是,gcc
and glibc
(Linux 上使用的 C 编译器和标准库)都生成最接近的可表示值,但其他实现则不会。
无论如何,根据您的错误消息,您希望该值介于0.00001
and 1.00000
。所以你的测试应该是这样的:
while (gap <= 0.00001F || gap >= 1.0000F) { ...
(假设你保留gap
as a float
.)
上述任何解决方案都可以。就我个人而言,我会做gap
a double
为了让比较更直观,也将比较改为compare against0.00001
and 1.0000
.
顺便说一句,E-05
后缀的意思是“十的-5次方”(E
代表Exponent
)。你会经常看到这样的情况;这是编写浮点常量的标准方法。