所有的整数值都是完美的双打吗?
我的问题是,是否所有的整数值保证有一个完美的双重表示。
考虑下面的代码示例打印“相同”:
// 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
?
我试了一些其他的数字,它一直是真实的,但无法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
分数中的部分也可以用来表示一个整数,通过使用指数来删除点之后的所有数字。
例如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:这取决于int
和double
的精度)。
考虑下面的代码示例打印“相同”:[…]这是保证适用于任何架构,任何编译器,a和b的任何值?
您的代码添加了两个int
, 然后将结果转换为double。 int
s的和将会溢出某些值,但是两个分开转换的double
s的和不会(通常)。 对于这些值,结果会有所不同。
简短的答案是“可能”。 便携式答案是“不是无处不在”。
这真的取决于你的平台,特别是在
-
double
的大小和表示 -
int
的范围
对于使用IEEE-754双打的平台,如果int
为53位或更小,则可能是正确的。 对于int
大于double
平台,显然是错误的。
您可能希望能够调查运行时主机上的属性,使用std::numeric_limits
和std::nextafter
。