所有的整数值都是完美的双打吗?

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

考虑下面的代码示例打印“相同”:

// 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任何值? 将我的任何整数转换为double ,总是被表示为i.0000000000000而不是,例如, i.000000000001

我试了一些其他的数字,它一直是真实的,但无法find这是巧合还是devise的任何事情。

注:这是不同于这个问题 (除了语言),因为我加了两个整数。

免责声明(正如Toby Speight所build议的):尽pipeIEEE 754的表示方式非常普遍,但允许使用任何其他符合语言要求的表示forms。


双数以mantissa * 2^exponent的forms表示,即一些位用于双数的非整数部分。

  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 

IEEE 754双重型示意图

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

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

由于一个普通的int通常是32位的,所以你可以把所有的int都表示为double,但是对于64位的整数当然不是这样。 更准确地说(正如LThode在注释中指出的那样):IEEE 754双精度可以保证高达53位(52位有效位+隐含的前导1位)。

:是32位整数,不是64位整数。

(这对于服务器/台式机通用CPU环境是正确的,但是其他体系结构可能会有不同的performance。)

Malcom McLean提出的实用答案 :对于几乎所有可能在现实生活中计算事物的整数,64位双精度是一个适当的整数types。


对于经验倾向,试试这个 :

 #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; } 

成功时间:0.85内存:15240信号:0


问题:关于分数差异的问题。 是否有可能有一个整数转换为一个双精度正好偏离了一个分数,但由于舍入转换回相同的整数?

答案是否定的,因为任何来回转换为相同值的整数实际上表示相同的double值。 对我来说,最简单的解释(由ilkkachubuild议)是使用指数2^exponent ,步长必须总是2^exponent 。 因此,除了最大的52(+1符号)比特整数以外,从来没有两个距离小于2的double值,这就解决了舍入问题。

不。假设你有一个64位整数types和一个64位浮点types(这是一个double )。 该整数types有2 ^ 64个可能的值,该浮点types有2 ^ 64个可能的值。 但是其中的一些浮点值(实际上大多数)并不代表整数值,所以浮点types可以表示比整数types更less的整数值。

答案是不。 这只适用于如果int是32位,而在大多数平台上,这是标准不能保证。

这两个整数可以共享相同的双重表示。

例如, 这个

 #include <iostream> int main() { int64_t n = 2397083434877565865; if (static_cast<double>(n) == static_cast<double>(n - 1)) { std::cout << "n and (n-1) share the same double representation\n"; } } 

将打印

n和(n-1)具有相同的双重表示

即2397083434877565865和2397083434877565864都将转换为相同的double

请注意,我在这里使用int64_t来保证64位整数,这取决于你的平台,也可能是int

你有两个不同的问题:

所有的整数值都是完美的双打吗?

这已经被其他人回答了(TL; DR:这取决于intdouble的精度)。

考虑下面的代码示例打印“相同”:[…]这是保证适用于任何架构,任何编译器,a和b的任何值?

您的代码添加了两个int然后将结果转换为double。 int s的和将会溢出某些值,但是两个分开转换的double s的和不会(通常)。 对于这些值,结果会有所不同。

简短的答案是“可能”。 便携式答案是“不是无处不在”。

这真的取决于你的平台,特别是在

  • double的大小和表示
  • int的范围

对于使用IEEE-754双打的平台,如果int为53位或更小,则可能是正确的。 对于int大于double平台,显然是错误的。

您可能希望能够调查运行时主机上的属性,使用std::numeric_limitsstd::nextafter