C 关于浮动特性的问题

C 关于浮动特性的问题,c,compare,precision,C,Compare,Precision,Q1:为什么不建议通过==或比较浮动呢=类似于V1 问题2:V2中的fabs()是否与我在V3中编程的方式相同? 问题3:可以使用(x>=y)和(x您知道机器使用0和1存储所有内容。 还要知道,并非每个浮点值都可以在有限位内用二进制表示。 计算机存储给定数字中可能最近的可表示二进制 因此,在计算机的眼中,它们是2.0000001和2.0000000之间的差异(但我们说它们是相等的!) 并非总是会出现此问题,但它是有风险的。因为在64位机器上,您会发现0.1*3=0.3000000000004:-

Q1:为什么不建议通过
==
比较浮动呢=类似于V1
问题2:V2中的
fabs()
是否与我在V3中编程的方式相同?

问题3:可以使用
(x>=y)
(x您知道机器使用0和1存储所有内容。
还要知道,并非每个浮点值都可以在有限位内用二进制表示。
计算机存储给定数字中可能最近的可表示二进制

因此,在计算机的眼中,它们是2.0000001和2.0000000之间的差异(但我们说它们是相等的!)


并非总是会出现此问题,但它是有风险的。

因为在64位机器上,您会发现
0.1*3=0.3000000000004
:-)


请参阅作为注释提供的@yano和@PM-77-1链接。

在处理浮点运算时,几乎每一步都可能引入一个小的舍入误差。将源代码中的十进制数转换为浮点格式?有一个小错误,除非数字是可以精确表示的。加两个数字?在浮点格式中,它们的精确和的位数往往超过适合的位数,因此必须对其进行四舍五入以适合。乘法和除法也是如此。求平方根?结果通常是非理性的,不能用浮点格式表示,因此它是四舍五入的。调用库获取余弦或对数?确切的结果通常是不合理的,因此它是四舍五入的。大多数数学库也有一些额外的错误,因为很难精确地计算这些函数

假设您计算了一些值,并在
x
中得到了一个结果。它包含了各种各样的错误。然后计算另一个值,并在
y
中得到结果。假设,如果用精确的数学计算,这两个值将相等。
x
y
中的错误完全相同的可能性有多大

这不太可能。如果以不同的方式计算
x
y
,它们会经历不同的误差,并且它们是否具有相同的总误差基本上是可能的。因此,即使精确的数学结果相等,
x==y
也可能因为错误而错误

类似地,两个精确的数学值可能不同,但错误可能重合,因此
x==y
返回true

因此
x==y
x!=y
通常不能用来判断所需的精确数学值是否相等

可以使用什么?不幸的是,这方面没有普遍的解决办法。您的示例使用
FLT\u EPSILON
作为错误阈值,但这并不有用。在执行多个浮点运算后,无论是绝对误差还是相对误差,误差都可能很容易累积到大于
FLT_EPSILON


为了进行比较,您需要了解累积误差可能有多大,这在很大程度上取决于您执行的特定计算。你还需要知道误报和漏报的后果是什么,避免误报两件事是相等的还是避免误报两件事是不相等的更重要?这些问题特定于每种算法及其数据。

试试这个:
float f;对于(f=0.0;f!=1.0;f+=0.1)printf(“%.1f\n”)当数字不相等时,通常不会出现问题。当您有两个您认为(或应该)相等但
==
的浮点数时,就会出现问题=说它们不相等。@谢谢你的例子,现在我看到问题了,它忽略了停止条件。这不是浮点数的存储方式。这意味着处理舍入错误的方式总是取决于情况,没有通用的方法?是的,差不多。浮点运算广泛用于计算近似值。将其用于精确或非常精确的工作需要工程上的努力。回答得好。作为一个非常简单的例子,我尝试了
double x=37;双y=功率(sqrt(x),2);如果(x==y)printf(“相等”\n);else printf(“不相等的\n”),果然,它打印了
不相等的
。 Source: Wikipedia Type | Size | Precision | Range Float | 4Byte ^= 32Bits | 6-9 decimal digits | (2-2^23)*2^127 Source: tutorialspoint Type | Size | Precision | Range Float | 4Byte ^= 32Bits | 6 decimal digits | 1.2E-38 to 3.4E+38 Source: chortle Type | Size | Precision | Range Float | 4Byte ^= 32Bits | 7 decimal digits | -3.4E+38 to +3.4E+38
#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;
}
a(+3.1415925) != b(+3.1415930)
#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;
}
x(+3.1415925) != y(+3.1415930)
#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;
}
x(+3.1415925) != y(+3.1415930)