我正在使用Visual Studio 6和一些用c编写的旧时代码.我发现代码看起来像这样的问题..
int x = 3;
float y = 3.0;
if(x == y){
do some crazy stuff
}
Run Code Online (Sandbox Code Playgroud)
这是一个有效的比较吗?是否有可能在运行时浮点数的分配是3.0000001,这会失败?
Dan*_*Tao 14
这通常(即,总是)是个坏主意.如您所料,从3到3.0000001的比较确实会失败.
大多数人所做的事情,如果真的需要进行int-float比较,那就选择一些容忍度阈值,并按照这样做:
int x = 3;
float y = 3.0;
// some code here
float difference = (float) x - y;
float tolerableDifference = 0.001;
if ((-tolerableDifference <= difference) && (difference <= tolerableDifference)) {
// more code
}
Run Code Online (Sandbox Code Playgroud)
我将在这里逆势而行.关于比较是否有效的第一个问题,答案是肯定的.这完全有效.如果您想知道浮点值是否恰好等于3,那么与整数的比较就可以了.整数隐式转换为浮点值以进行比较.实际上,以下代码(至少使用我使用的编译器)生成了相同的汇编指令.
if ( 3 == f )
printf( "equal\n" );
Run Code Online (Sandbox Code Playgroud)
和
if ( 3.0 == f )
printf( "equal\n" );
Run Code Online (Sandbox Code Playgroud)
所以它取决于逻辑和预期目标是什么.语法没有任何内在错误.
还没有其他人引用它,我有一段时间没有把它联系起来,所以这里有关于浮点表示和算术的可怕边缘的经典论文:每个计算机科学家应该知道浮点数.
对于非数学家而言,这篇论文是一本具有挑战性的读物,但关键点在大量的数学支持之间得到了很好的说明.
对于此讨论,此处其他答案所提出的观点均有效.浮点运算是不精确的,因此对于精确相等的比较通常是一个坏主意.因此,epsilon是你的朋友.
精确比较规则的一个例外是完全为零的测试.在分割或对数之前测试正好零是完全合法的并且通常是明智的,因为对于任何非零值都很好地定义了答案.当然,在存在IEEE规则和NaN的情况下,您可以稍后滑动并测试NaN或Inf.
好吧,我想当你听到比较浮点数是否相等是一个菜鸟错误时,你不会感到太惊讶。
问题是许多小于整数值的增量实际上无法用 IEEE 浮点精确表示。因此,如果您通过尝试将其“索引”到值 3.0(例如以 0.1 为增量)来获得浮点数,则很可能您的相等比较永远无法进行真。
仅从类型强度的角度来看,这也是一个坏主意。您应该将浮点数转换为 int,检查您的 int 是否“足够接近”(例如 < 3.1 和 > 2.9 或类似的东西),或者如果您试图使浮点数对计数器之类的东西执行双重任务,那就更好了,避免整个想法。