C++ 精确除法会失去精度吗?

C++ will exact division lose precision?

Q1:一个整数除以它的约数会失去精度吗?

int a=M*N,b=N;//M and N are random non-zero integers.
float c=float(a)/b;
if (c==M)
cout<<"accurate"<<endl;

Q2:传递一个浮点值会失去精度吗?

float a=K;//K is a random float;
if (a==K)
cout<<"accurate"<<endl;

Q1:Will dividing a integer by its divisor lose precision ?

是的。我使用以下程序得出了一些数字:

#include <iostream>
#include <climits>

int main()
{
   int M = 10;
   int N = 7;
   int inaccurateCount = 0;
   for (; M < INT_MAX && inaccurateCount < 10; ++M )
   {
      int a = M*N;
      float c = float(a)/N;
      if ( c != M )
      {
         std::cout << "Not accurate for M: " << M << " and N: " << N << std::endl;
         inaccurateCount++;
      }
   }

   return 0;
}

这是输出:

Not accurate for M: 2396747 and N: 7
Not accurate for M: 2396749 and N: 7
Not accurate for M: 2396751 and N: 7
Not accurate for M: 2396753 and N: 7
Not accurate for M: 2396755 and N: 7
Not accurate for M: 2396757 and N: 7
Not accurate for M: 2396759 and N: 7
Not accurate for M: 2396761 and N: 7
Not accurate for M: 2396763 and N: 7
Not accurate for M: 2396765 and N: 7

Q2:Will passing a float value lose precision ?

不,不应该。

它并不准确,但要获得更准确的答案,您可以使用值类型 double 和 long

案例 1:是的,它在某些情况下会失去精度。对于较小的 M 值,它将是准确的。

情况 2:不,它不会丢失精度。

Q1:Will dividing a integer by its divisor lose precision ?

您实际上问过将 int 转换为 float 是否会丢失精度。 是的,它通常会这样做。在当今的 32 位(或更宽)计算机体系结构中,int 存储 32 位数据:1 位符号加上 31 位有效数。 float 也存储 32 位数据,但它们是:1 位符号、8 位指数和 23 位小数部分,参见。 IEEE 754 single-precision floating point format(它可能不会在 16 位架构上丢失精度,但我无法检查。)

根据浮点数的不同,它会以不同的表示形式存储,一种是归一化形式,其中小数部分前面加上一个隐藏的小数部分,这样,我们得到一个 24 位的有效数字。这小于存储在 int.

中的值

例如整数 01010101 01010101 01010101 01010101(二进制,space 只是为了更好的阅读)不能表示为 float 而不丢失精度。在规范化形式中,这将是 1,010101 01010101 01010101 01010101 * 2^30。所以我们在逗号后有 30 个有效位二进制数字,不能在不损失精度的情况下存储在 23 位(小数部分)中。实际的回合模式定义了如何缩短值。

请注意,它不取决于值是否实际 "high"。整数 01000000 00000000 00000000 00000000 是标准化形式 1,000000 00000000 00000000 00000000 * 2^30。此数字在逗号后有零有效位,可以在不丢失精度的情况下存储。

Q2: Will passing a float value lose precision ?

没有

Q1:Will dividing a integer by its divisor lose precision ?

如果 a 太大可能会降低精度,否则(如果 a 足够小可以精确表示为浮点数)则不会。当您转换 a 时,精度损失实际上可能已经发生。除法也会降低精度,但有时这些精度损失可能会相互抵消。

例如 N = 8388609M=5。您有(二进制)尾数 100...001 并与 101 相乘,最后得到 101000...0000101,但是最后两位将四舍五入为零并且您在 (float)(N*M ), 但是当你除以 5 时,你得到 1000...00 和 100 的余数,这意味着它应该四舍五入并得到原始数字。

Q2:Will passing a float value lose precision ?

不,它不会丢失精度。但是,您的代码仍可能无法将其识别为准确的。

如果 KNaN(例如 0.0/0.0),那么 x 也会变成 NaN -然而 NaN 不应该(需要)比较相等。在这种情况下,有人可能会争辩说你失去了精度,我同意,但并不是在 x=K 点失去了精度 - 你在生成 K.

时已经失去了精度