float
变量的尾数位总共为 23,而 double
变量为 53。
这意味着可以精确表示的数字
float
变量总共有 log10(2^23) = 6.92368990027 = 6
通过double
变量log10(2^53) = 15.9545897702 = 15
让我们看一下这段代码:
float b = 1.12391;
double d = b;
cout<<setprecision(15)<<d<<endl;
打印
1.12390995025635
但是这段代码:
double b = 1.12391;
double d = b;
cout<<setprecision(15)<<d<<endl;
打印1.12391
有人可以解释为什么我会得到不同的结果吗?我把一个6位的float变量转换成了double,编译器肯定知道这6位很重要。为什么?因为我没有使用更多无法在浮点变量中正确表示的数字。因此,它没有打印正确的值,而是决定打印其他内容。
从 float
转换至 double
保留值(value)。因此,在第一个片段中,d
恰好包含 float
的近似值精度为 112391/100000。有理数 112391/100000 存储在 float
中格式为 9428040/223。如果执行此除法,结果正好是 1.12390995025634765625: float
近似值不是很接近。 cout <<
将表示形式打印到小数点后的 14 位数字。第一个省略的数字是 7,因此最后打印的数字 4 向上舍入为 5。
在第二个片段中,d
包含 double
的近似值112391/100000 值的精度,1.123909999999999964614971759147010743618011474609375(换句话说,5061640657197974/252)。这种近似更接近有理数。如果它在小数点后打印 14 位,则最后一位将全部为零(四舍五入后,因为第一个省略的数字将是 9)。 cout <<
不打印尾随零,因此您会看到 1.12391 作为输出。
Because I'm not using more digits that can't all be represented correctly in a float variable
当您错误地将 log10 应用于 223(应该是 224)时,您会得到可以存储在 float 中的小数位数。因为float
的表示不是十进制,这七位左右的数字一般都不是零。它们是编译器为您编写的数字选择的最接近二进制表示形式的十进制数字。