回 帖 发 新 帖 刷新版面

主题:关系表达式10*0.1=1的值为真为假?

为什么0.1*10=1的值为假,而10*1=10的值为真呢?谢谢!

回复列表 (共21个回复)

11 楼

的确属于一家之见。

我说了5楼的是对的……楼上的看5楼的内容了吗?

12 楼

再顶一下,楼上的朋友,虽然五楼运行的结果是那样,你有没有想过为什么?我现在单双精度都试了,都不行,编译器在其中做了什么手脚呢?
单单说是精度问题,也是不确切的吧?

13 楼

我以前在一个讨论程序效率的帖子中说过,编程时尽量使用变量而少用立即数。如果本例要是先将10*.1的值赋给一个单精度变量,就不会出现问题。而赋给一个双精度变量时会出现与直接用立即数同样的问题。

我是由此想到可能是QB在处理立即数时有特别的方式,只是这个方式有毛病。

14 楼

如果想完全弄明白,你最好去学汇编,而不是basic。
我会没考虑过为什么吗?难道精度误差是很难理解的事情?

你用整型变量就不会错了。

15 楼

楼上的话可不能这么说,精度会误差谁不知道,谁不理解,要误差,一起误差行不?我就弄不明白了,我单双精度都不行,这碍汇编啥事了,我说是编译器的bug行不?

16 楼

试了下c
#include<stdio.h>
int main()
{
  if(0.1*10==1)printf("ok!");
  return 0;
}
结果输入ok,由此可见,不单单是精度的问题
问题在于qbasic编译器在其中做了什么
我们知道,要比较两个数的时候,如果类型不同,需要转化类型,才能比较
而转化过程中,就像faintzw说的那样,会产生精度误差,那么这是导致不相等的原因之一
我尝试过用变量保存值,再比较,结果相等,可见不单单是精度的问题
也就是说qbsic有可能在立即数变型不相等的情况,直接判断表达式为假
,这仅是我的猜测,仅供参考
由此可见,就像staa说的那样,尽量用变量保存,再来比较,少用立即数
不知道我说的在不在理?有批评意见的,欢迎指出

17 楼

又试了下
a#=0.1
print a#,0.1#
结果不一样,无语了

18 楼


编译器的bug?呵呵……与其说是bug,倒不如说是普遍存在的问题……
你应该知道pascal的精度误差也不小吧

19 楼

说实在的,如果考试,绝对会填精度误差.
但我本人,对这个观点保持怀疑态度
误差是肯定有的,但是我想说的是0.1*10=1这并不一定是误差的问题吧
为啥呢?因为就算你有误差,你总得放到一个类型里,才能比较吧?我试遍了类型,怎么就不相等呢?难不成,0.1*10这个值不在计算机里,我就不明白了
pascal程序如下

begin
  if(0.1*10=1) then write('true!');
end.
结果我得到了很肯定的答案,true
所以,我理由相信,是不是编译器做了啥不该做的事

20 楼

何谓basic?beginner's all-purpose symbolic instruction code.“初学者”。
既然是为初学者准备的,自然要弄一些方便初学者的东西。
cls
a#=1
print a#
毫无疑问输出1

但PASCAL(FPC):
var
  a:real;
begin
  a:=1;
  writeln(a)
end.
输出:1.000000000000000E+000

看到了吗?
不管变量是什么类型,只要能用整数表示,basic就不会出现科学计数法。
而pascal却严格按照类型输出。basic这种自动的类型转换应该就是为了方便初学者吧。不提供指针也可能是考虑到初学者问题。

计算机中浮点数是离散分布的。所以绝大多数的数只能以一个接近它的数来表示,接近的程度依赖于数的精度(单、双精度)。像0.1可能在计算机里保存为0.09999999或者0.10000000001。所以,判断实数相等问题,一般都比较保存的数和精确的数的相似程度,只要两者的差的绝对值小于能允许的范围,则可以认为二者是相等的。如abs(0.1-0.1000001)<=0.00001,则可以认为计算机中存储的数(0.1000001)是0.1

我来回复

您尚未登录,请登录后再回复。点此登录或注册