在C中,当设置浮动时,
int main(int argc, char *argv[]) {
float temp = 98.6f;
printf("%f\n", temp);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它似乎总是会出现某种舍入错误,
98.599998
Run Code Online (Sandbox Code Playgroud)
但是当我把它做得更精确的时候,
float temp = 96.600000f;
Run Code Online (Sandbox Code Playgroud)
它仍会打印不同的数字.这应该如何解决?
Jon*_*eet 10
它仍会打印不同的数字.这应该如何解决?
通过使用不同的数据类型,如果需要精确的十进制值.
二进制浮点数是精确的 - 它只是它们是精确的二进制值.
例如,如果要表示基数3中的数字,则十进制是不精确的.没有十进制0.1的精确二进制表示,就像没有"三分之一"的精确十进制表示一样.
这都是计算出您的要求,并使用与之匹配的数据类型的问题.对于精确的十进制值,您可能最好使用第三方库...或者保持一个您知道的整数按逻辑缩放100或10,000或其他任何值.
这是以二进制形式表示十进制数的基本限制.二进制浮点数以2的幂表示,而十进制数以10的幂表示,而C float则无法准确表示所有十进制数.
您的示例编号96.1可以写为:
96.1 = 9*10^1 + 9*10^0 + 1*10^-1
Run Code Online (Sandbox Code Playgroud)
要以二进制表示,您可以获得整数96:
96 = 1*2^6 + 1*2^5
Run Code Online (Sandbox Code Playgroud)
但是代表0.1在基数2中是有问题的.二进制中前几个小数位的位值是:
2^-1 = 0.5
2^-2 = 0.25
2^-3 = 0.125
2^-4 = 0.0625
2^-5 = 0.03125
2^-6 = 0.015625
2^-7 = 0.0078125
2^-8 = 0.00390625
2^-9 = 0.001953125
... and so on
Run Code Online (Sandbox Code Playgroud)
所以你需要使用这些地方值的组合来加起来小数约为0.1.因此,您必须从b0.0001(d0.0625)开始,因为它是小于d0.1的第一个位置,并添加更多较小的位置值以越来越接近0.1.例如:
b0.001 = d0.125 // too high, try lower
b0.0001 = d0.0625 // too low, so add smaller places
b0.00011 = d0.09375 // good, closer... rounding error is 0.0625
b0.000111 = d0.109375 // oops, a little high
b0.00011001 = d0.09765625 // getting better - how close do you need?
...
Run Code Online (Sandbox Code Playgroud)
等等 - 你明白了.因此,由于基本表示,二进制值只能近似小数.
关于浮点舍入误差和表示限制的文章很多.绝对值得做一些关于这个主题的背景阅读.
有几种方法可以解决这个问题:
float但仍然意识到这些限制并仔细设计算法以最小化舍入误差