Q1:为什么不建议像在V1中那样按==
或!=
比较浮动
Q2:V2中的fabs()
的工作方式是否与我在V3中将其编程的方式相同
Q3:可以使用(x >= y)
和(x <= y)
吗
Q4:根据维基百科,float
的精度在6到9位之间,在我的情况下是7位。那么,它取决于什么,我的float
的精度在6到9位数之间?参见[1]
[1]浮动特性
来源:维基百科类型|大小|精度|范围浮点|4字节^=32位|6-9位小数|(2-2^23)*2^127来源:tutorialspoint类型|大小|精度|范围浮点|4字节^=32位|6位小数|1.2E-38到3.4E+38来源:chortle类型|大小|精度|范围Float|4Byte^=32Bits|7位十进制数字|-3.4E+38到+3.4E+38
以下三种代码产生相同的结果,但不建议使用第一种变体。
1.变体
#include <stdio.h> // printf() scanf()
int main()
{
float a = 3.1415926;
float b = 3.1415930;
if (a == b)
{
printf("a(%+.7f) == b(%+.7f)n", a, b);
}
if (a != b)
{
printf("a(%+.7f) != b(%+.7f)n", a, b);
}
return 0;
}
V1输出:
a(+3.1415925) != b(+3.1415930)
2.变体
#include <stdio.h> // printf() scanf()
#include <float.h> // FLT_EPSILON == 0.0000001
#include <math.h> // fabs()
int main()
{
float x = 3.1415926;
float y = 3.1415930;
if (fabs(x - y) < FLT_EPSILON)
{
printf("x(%+.7f) == y(%+.7f)n", x, y);
}
if (fabs(x - y) > FLT_EPSILON)
{
printf("x(%+.7f) != y(%+.7f)n", x, y);
}
return 0;
}
V2输出:
x(+3.1415925) != y(+3.1415930)
3.变体:
#include <stdio.h> // printf() scanf()
#include <float.h> // FLT_EPSILON == 0.0000001
#include <stdlib.h> // abs()
int main()
{
float x = 3.1415926;
float y = 3.1415930;
const int FPF = 10000000; // Float_Precission_Factor
if ((float)(abs((x - y) * FPF)) / FPF < FLT_EPSILON) // if (x == y)
{
printf("x(%+.7f) == y(%+.7f)n", x, y);
}
if ((float)(abs((x - y) * FPF)) / FPF > FLT_EPSILON) // if (x != y)
{
printf("x(%+.7f) != y(%+.7f)n", x, y);
}
return 0;
}
V3输出:
x(+3.1415925) != y(+3.1415930)
感谢您的帮助、链接、参考资料和提示!
在处理浮点运算时,几乎每一步都可能引入较小的舍入误差。将源代码中的十进制数字转换为浮点格式?这是一个小错误,除非数字是可以精确表示的。加两个数字?在浮点格式中,它们的精确和通常比适合的位数多,因此必须四舍五入才能适合。乘法和除法也是如此。取平方根?结果通常是无理的,不能用浮点格式表示,所以它是四舍五入的。调用库来获取余弦还是对数?确切的结果通常是不合理的,所以它是四舍五入的。大多数数学库也有一些额外的错误,因为很难精确地计算这些函数。
所以,假设你计算了一些值,并在x
中得到了一个结果。它包含了各种错误。然后计算另一个值,并在y
中得到结果。假设,如果用精确的数学计算,这两个值将相等。x
和y
中的错误完全相同的可能性有多大?
这不太可能。如果以不同的方式计算x
和y
,它们经历了不同的误差,并且它们是否具有相同的总误差本质上是偶然的。因此,即使精确的数学结果是相等的,x == y
也可能因为误差而为假。
类似地,两个精确的数学值可能不同,但误差可能一致,因此x == y
返回true。
因此CCD_ 16和CCD_。
可以使用什么?不幸的是,这并没有一个通用的解决方案。您的示例使用FLT_EPSILON
作为错误阈值,但这没有用处。在进行了多次浮点运算之后,误差可以容易地累积为大于FLT_EPSILON
,无论是作为绝对误差还是相对误差。
为了进行比较,您需要了解累积误差可能有多大,这在很大程度上取决于您执行的特定计算。你还需要知道假阳性和假阴性的后果是什么——避免谎称两件事相等更重要还是避免谎称两者不相等更重要?这些问题针对每种算法及其数据。
因为在64位机器上,您会发现0.1*3 = 0.30000000000000004
:-)
请参阅作为评论提供的链接@yano和@PM-77-1。
您知道机器使用0和1存储所有内容。还要知道,并不是每个浮点值都可以用有限位内的二进制表示。计算机存储给定数字中可能最接近的可表示二进制数。
因此,在计算机眼中,它们是2.00000001和2.0000000之间的差(但我们说它们是相等的!)。
这种麻烦并不总是出现,但它是有风险的。