Representing integers in doubles (5个答案)
3年前关闭。
我的问题是,是否所有整数值都保证具有完美的 double 表示形式。
考虑下面的代码示例,它显示“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;
}
}
是否可以保证对任何体系结构,任何编译器,
a
和
b
的任何值都是正确的?是否将任何整数
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
小数部分也可以通过使用指数来表示整数,该指数去除点后的所有数字。
例如。 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 整数,该整数恰好与正确值相差一个分数,但由于舍入而又转换回相同的整数?
答案是否定的,因为任何来回转换为相同值的整数实际上都表示相同的整数倍。对我而言,最简单的解释(由ilkkachu建议)是,使用指数
2^exponent
,步长必须始终为2的幂。因此,除了最大的52(+1号)位整数之外,再也没有两个距离小于2的double值,这解决了舍入问题。