时间:2021-07-01 10:21:17 帮助过:45人阅读
>>> def show(x):
... """打印一个数,20 位精度"""
... print('{:.20f}'.format(x))
...
>>> show(1.5)
1.50000000000000000000
>>> show(1.25)
1.25000000000000000000
>>> show(1.245)
1.24500000000000010658
>>> show(1.45)
1.44999999999999995559
>>> show(1.415)
1.41500000000000003553
四舍五入是基于十进制的,在二进制无法精确表示的时候是会有误差的。>>> Decimal(1.45)
Decimal('1.4499999999999999555910790149937383830547332763671875')
>>> Decimal('1.45')
Decimal('1.45')
>>> Context(prec=2, rounding=ROUND_HALF_UP).create_decimal('1.45')
Decimal('1.5')
>>> Decimal('1.45').normalize(Context(prec=2, rounding=ROUND_HALF_UP))
Decimal('1.5')
>>> Decimal(Decimal('1.45').quantize(Decimal('.1'), rounding=ROUND_HALF_UP))
Decimal('1.5')
Note that this is in the very nature of binary floating-point: this is not a bug in Python, and it is not a bug in your code either. You’ll see the same kind of thing in all languages that support your hardware’s floating-point arithmetic (although some languages may not display the difference by default, or in all output modes).
round(number[, ndigits])
Return the floating point value number rounded to ndigits digits after the decimal point. If ndigits is omitted, it defaults to zero. The result is a floating point number. Values are rounded to the closest multiple of 10 to the power minus ndigits; if two multiples are equally close, rounding is done away from 0.
round(0.5) is 1.0 and round(-0.5) is -1.0)
题主测试的和那个bug无关。round是四舍六入五成双的。
python 的官方实现确实有问题,至于为什么作者不改进,原作者可能是什么心态,可以参见刘海洋的答案。大致心态也许是:反正这个错误不在我,所以虽然有方法,但我也不会去解决这个问题。#include
float my_round(float src, int idx)
{
int i;
for (i=idx;i--;)
src *=10;
float dest = (int)src;
if (src >= dest+0.5)
dest += 1;
for (i=idx;i--;)
dest /=10;
return dest;
}
int main()
{
printf("result=%f\n", my_round(1.5, 0));
printf("result=%f\n", my_round(1.25, 1));
printf("result=%f\n", my_round(1.245, 2));
printf("result=%f\n", my_round(1.45, 1));
printf("result=%f\n", my_round(1.415, 2));
printf("result=%f\n", my_round(2.675, 2));
}
两个问题,一个是expect: 1.0
actual: 1
expect: 1.1
actual: 1.100000000000000088817841970012523233890533447265625
expect: 1.2
actual: 1.1999999999999999555910790149937383830547332763671875
expect: 1.3
actual: 1.3000000000000000444089209850062616169452667236328125
expect: 1.4
actual: 1.399999999999999911182158029987476766109466552734375
expect: 1.5
actual: 1.5
expect: 1.6
actual: 1.600000000000000088817841970012523233890533447265625
expect: 1.7
actual: 1.6999999999999999555910790149937383830547332763671875
expect: 1.8
actual: 1.8000000000000000444089209850062616169452667236328125
expect: 1.9
actual: 1.899999999999999911182158029987476766109466552734375
很简单,因为2.675在表示的时候可能是2.6749,所以round以后还是2.67了
你的需求本质是:精确小数运算。然而,float不是为了满足这一需求而设计的,decimal才是。所以,为float单独定制一个round,不符合float的设计意图,也很难实现。以你的函数为例,temp*10这个操作在float下不是精确的。