c – 所有整数值都完美地表示为双精度数吗?
作者:互联网
参见英文答案 > Representing integers in doubles 5个
我的问题是,是否保证所有整数值都具有完美的双重表示.
请考虑以下打印“相同”的代码示例:
// 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的任何值?将我转换为double的任何整数,总是表示为i.0000000000000而不是,例如,i.000000000001?
我尝试了其他一些数字并且它总是如此,但无法找到关于这是巧合还是设计的任何信息.
注意:这与this question(除了语言)不同,因为我添加了两个整数.
解决方法:
免责声明(由Toby Speight建议):尽管IEEE 754表示很常见,但允许实现使用满足语言要求的任何其他表示.
双精度以尾数* 2 ^指数的形式表示,即一些位用于双数的非整数部分.
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位,因此您可以将所有整数表示为double,但对于64位整数,当然这不再是真的.更确切地说(正如LThode在评论中指出的那样):IEEE 754双精度可以保证最多53位(52位有效数和隐含前导1位).
答案:32位整数是,64位整数不.
(这对于服务器/桌面通用CPU环境是正确的,但其他体系结构可能表现不同.)
Malcom McLean提出的实用答案:对于几乎所有可能在现实生活中计算事物的整数,64位双精度数是一个足够的整数类型.
对于经验倾向,请尝试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
Subquestion:
关于分数差异的问题.是否有可能有一个整数转换为一个double,它正好偏离正确的值一小部分,但由于四舍五入而转换回相同的整数?
答案是否定的,因为任何来回转换为相同值的整数实际上代表double中的相同整数值.对我来说,最简单的解释(由ilkkachu建议)就是使用指数2 ^指数,步长必须始终是2的幂.因此,除了最大的52(1符号)位整数之外,从不存在两个距离小于2的双值,这解决了舍入问题.
标签:c,precision,standards,double,ieee-754 来源: https://codeday.me/bug/20190923/1815361.html