我的问题是是否保证所有整数值都具有完美的双重表示。
考虑以下代码示例打印"相同":
// 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(除了语言)不同,因为我添加了两个整数。
答案 0 :(得分:70)
免责声明(由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
分数中的部分也可以通过使用指数来表示整数,该指数删除点之后的所有数字。
E.g。 2,9979·10 ^ 4 = 29979.
由于公共int
通常为32位,因此您可以将所有int
表示为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;
}
成功时间:0.85记忆:15240信号:0
<强> Subquestion 强>: 关于分数差异的问题。是否有可能有一个整数转换为一个double,它正好偏离正确的值一小部分,但由于四舍五入而转换回相同的整数?
答案是否定的,因为任何来回转换为相同值的整数实际上代表double中的相同整数值。对我来说,最简单的解释(由ilkkachu建议)就是使用指数2^exponent
步长必须始终是2的幂。因此,除了最大的52(+1符号)位整数之外,永远不会有两个距离小于2的双精度值,这解决了舍入问题。
答案 1 :(得分:15)
没有。假设您有64位整数类型和64位浮点类型(这是double
的典型类型)。该整数类型有2 ^ 64个可能的值,并且该浮点类型有2 ^ 64个可能的值。但是其中一些浮点值(实际上大多数)并不表示整数值,因此浮点类型可以表示比整数类型更少的整数值。
答案 2 :(得分:11)
答案是否定的。这只适用于int
为32位的情况,虽然在大多数平台上都是正确的,但标准并不保证。
两个整数可以共享相同的双重表示。
例如,this
#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
。
答案 3 :(得分:4)
您有两个不同的问题:
是否所有整数值都完美地表示为双精度?
其他人已经回答了这个问题(TL; DR:这取决于int
和double
的精确度。)
考虑以下打印“Same”的代码示例:[...]对于任何架构,任何编译器,a和b的任何值,这是否保证都是正确的?
您的代码会添加两个int
和,然后会将结果转换为double。对于某些值,int
s 的总和将溢出,但两个单独转换的double
的总和不会(通常)。对于这些值,结果会有所不同。
答案 4 :(得分:2)
简短的回答是&#34;可能&#34;。便携式答案是&#34;并非无处不在&#34;。
这实际上取决于您的平台,尤其是
double
int
对于使用IEEE-754双打的平台,如果int
为53位或更小,则可能为真。对于int
大于double
的平台,它显然是错误的。
您可能希望能够使用std::numeric_limits
和std::nextafter
调查运行时主机上的属性。