为什么以下两个结果不同?无论如何,以下乘法的结果应该是整数。
uint16_t test = 500.00 * 128.51;
std::cout << test << std::endl; ----> 64254
但
float test = 500.00 * 128.51;
std::cout << test << std::endl; ----> 64255
答案 0 :(得分:5)
(从评论转发)
要完成previously linked duplicate,500.00 * 128.51实际上略小于64255(因为128.51无法在二进制FP中准确表示)。
当转换为整数类型时,将丢弃小数(值截断),因此64254.99999 ...变为64254。
OTOH,当保留为double
时,保留64254.9999 ...,默认ostream::operator<<
行为是在打印时在某个小数位置舍入,所以在显示它时你会看到它就像64255一样。
答案 1 :(得分:3)
以下乘法的结果不具有小数。
也许它不是基数10(十进制),但是计算机不能在基数10中工作。它们在基数2中工作,而在基数2中,128.51具有更多小数小数位数可以存储在float
(或实际上,任何类似的格式 - 它需要无限的位置,就像尝试写出十进制的1/3一样)。
此错误贯穿始终,尽管数学64255是一个整数,但乘法的结果更接近于64254.9999999999927240。
默认情况下, std::cout
会自动将其舍入(因为它知道发生了这种事情);但是,在转换为uint16_t
期间,会发生愚蠢的截断,导致错误的64254。
使用一些I / O操纵器魔术,我们可以更清楚地看到这一点:
#include <iostream>
#include <iomanip>
int main()
{
std::cout << std::fixed << std::setprecision(16) << (500.00 * 128.51) << std::endl;
std::cout << uint16_t(500.00 * 128.51) << std::endl;
}
// 64254.9999999999927240
// 64254