Tho*_*mas 57 c++ precision double standards ieee-754
我的问题是,是否保证所有整数值都具有完美的双重表示.
请考虑以下打印"相同"的代码示例:
// 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;
}
}
Run Code Online (Sandbox Code Playgroud)
对于任何架构,任何编译器,任何值a和b?保证这是真的吗?i转换为的任何整数是否double总是表示为i.0000000000000和不表示为,例如,i.000000000001?
我尝试了其他一些数字并且它总是如此,但无法找到关于这是巧合还是设计的任何信息.
注意:这与这个问题(除了语言)不同,因为我添加了两个整数.
Beg*_*ner 74
免责声明(由Toby Speight建议):尽管IEEE 754表示很常见,但允许实现使用满足语言要求的任何其他表示.
双精度以表格形式表示mantissa * 2^exponent,即一些位用于双数的非整数部分.
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
Run Code Online (Sandbox Code Playgroud)
分数中的部分也可以通过使用指数去除点后的所有数字来表示整数.
例如2,9979·10 ^ 4 = 29979.
由于公共int通常是32位,你可以将所有ints 表示为double,但对于64位整数,当然这不再是真的.更确切地说(正如LThode在评论中指出的那样):IEEE 754双精度可以保证最多53位(52位有效数+隐含前导1位).
答案:32位整数是,64位整数不.
(这对于服务器/桌面通用CPU环境是正确的,但其他体系结构可能表现不同.)
Malcom McLean提出的实用答案:对于几乎所有可能在现实生活中计算事物的整数,64位双精度数是一个足够的整数类型.
对于经验倾向,试试这个:
#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;
}
Run Code Online (Sandbox Code Playgroud)
成功时间:0.85内存:15240信号:0
子问题:关于分数差异的问题.是否有可能有一个整数转换为一个double,它正好偏离正确的值一小部分,但由于四舍五入而转换回相同的整数?
答案是否定的,因为任何来回转换为相同值的整数实际上代表double中的相同整数值.对我来说,最简单的解释(由ilkkachu建议)就是使用指数2^exponent,步长必须始终是2的幂.因此,除了最大的52(+1符号)位整数之外,从不存在两个距离小于2的双值,这解决了舍入问题.
Pet*_*ker 15
不.假设您有64位整数类型和64位浮点类型(对于a来说是典型的double).该整数类型有2 ^ 64个可能的值,并且该浮点类型有2 ^ 64个可能的值.但是其中一些浮点值(实际上大多数)并不表示整数值,因此浮点类型可以表示比整数类型更少的整数值.
Cor*_*sto 11
答案是不.这仅在ints为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";
}
}
Run Code Online (Sandbox Code Playgroud)
将打印
n和(n-1)共享相同的双重表示
即2397083434877565865和2397083434877565864将转换为相同double.
请注意,我int64_t在这里用来保证64位整数,这取决于你的平台 - 也可能是什么int.
| 归档时间: |
|
| 查看次数: |
8693 次 |
| 最近记录: |