c++ - 所有整数值都完美地表示为 double 吗?

标签 c++ double standards precision ieee-754

我的问题是是否所有整数值都保证具有完美的双重表示。

考虑以下打印“Same”的代码示例:

// Example program
#include <iostream>
#include <string>

int main()
{
  int a = 3;
  int b = 4;
  double d_a(a);
  double d_b(b);

  double int_sum = a + b;
  double d_sum = d_a + d_b;

  if (double(int_sum) == d_sum)
  {
      std::cout << "Same" << std::endl;
  }
}

对于任何架构、任何编译器、ab 的任何值,这是否都保证是正确的?将任何整数 i 转换为 double,总是表示为 i.0000000000000 而不是,例如,如 i.000000000001

我尝试了其他一些数字,它总是正确的,但无法找到任何关于这是巧合还是设计的信息。

注意:这与 this question 不同。 (除了语言)因为我要添加两个整数。

最佳答案

免责声明(由 Toby Speight 建议):尽管 IEEE 754 表示非常普遍,但允许实现使用满足语言要求的任何其他表示。


double 以 mantissa * 2^exponent 的形式表示,即某些位用于 double 的非整数部分。

             bits        range                       precision
  float        32        1.5E-45   .. 3.4E38          7- 8 digits
  double       64        5.0E-324  .. 1.7E308        15-16 digits
  long double  80        1.9E-4951 .. 1.1E4932       19-20 digits

Schematic of IEEE 754 double type

分数中的部分也可以通过使用指数来表示整数,去除点后面的所有数字。

例如2,9979 · 10^4 = 29979。

由于一个常见的 int 通常是 32 位的,您可以将所有 int 表示为 double ,但对于 64 位整数,这当然不再适用。更准确地说(正如 LThode 在评论中指出的那样):IEEE 754 double 最多可以保证 53 位(52 位有效位 + 隐式前导 1 位)。

答案:32 位整数为是,64 位整数为否。

(这对于服务器/桌面通用 CPU 环境是正确的,但其他架构的行为可能会有所不同。)

实用答案正如 Malcom McLean 所说:64 位 double 对于几乎所有可能在现实生活中计算事物的整数来说是一种足够的整数类型。


如果您有经验,请尝试 this :

#include <iostream>
#include <limits>
using namespace std;

int main() {
    double test;
    volatile int test_int;
    for(int i=0; i< std::numeric_limits<int>::max(); i++) {
        test = i;
        test_int = test;

        // compare int with int:
        if (test_int != i)
            std::cout<<"found integer i="<<i<<", test="<<test<<std::endl;
    }
    return 0;
}

Success time: 0.85 memory: 15240 signal:0


子问题: 关于分数差异的问题。是否有可能有一个整数转换为与正确值相差一个分数的 double ,但由于四舍五入而转换回相同的整数?

答案是否定的,因为任何来回转换为相同值的整数实际上都以 double 表示相同的整数值。对我来说,最简单的解释(ilkkachu 建议)是使用指数 2^exponent 步宽必须始终是 2 的幂。因此,在最大的 52(+1 符号)位整数之外,永远不会有两个距离小于 2 的 double 值,从而解决了舍入问题。

关于c++ - 所有整数值都完美地表示为 double 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43655668/

相关文章:

c++ - 碰撞。 QObject::connect 在静态对象实例的构造函数中

c++ - 传入 A::operator new() 的大小是否总是等于 sizeof(A)?

c++ - 如果删除未使用的引用类,则 DLL 无法加载

c++ - 将 FILE * stdout 重定向到 C++ 中的字符串

c++ - 3D 模型文件并从中创建三角形网格

java - 为什么我只能输入 "1,5"而不能输入 "1.5"

ios - NSUserDefault 无法检索 double 值

Java获取 double 的前2位小数

c - 什么是 C11 cor 1 :2012?

c++ - C++标准:32位和64位的奇怪的有符号/无符号算术除法行为