Python 做除法算比例,结果加起来不是 100

2020-03-31 10:32:09 +08:00
 mw717if

'

    divisor = sum(list(dept_id2count.values()))
    
    divisor = str(divisor)
    
    getcontext().prec = 4
    
    dept_id2p = {}
    
    for dept_id in dept_id2count:
    
        count = dept_id2count[dept_id]
        
        dividend = str(100 * count)  # 被除数
        
        dept_id2p[dept_id] = Decimal(dividend) / Decimal(divisor)
        
        print(Decimal(dividend) / Decimal(divisor))

计算代码如上,输出如下。算每个 count 占总数的比例,最后把比例存到 mysql,保留两位小数。 """

1.781

6.334

0.009013

0.9311

0.02471

0.1105

14.28

24.70

0.4394

11.09

0.01872

4.541

0.06418

13.75

2.486

1.953

0.4429

4.833

4.242

0.08313

1.931

0.7320

0.06604

1.762

3.397

99.99

"""

问题是这些比例加起来不是 100,

一开始用 float 保留两位小数,

后来改成 decimal 四位有效数字,

都没有解决。

求助各位大佬,有没有什么好办法

4670 次点击
所在节点    Python
34 条回复
viggoc
2020-03-31 10:37:28 +08:00
保留有效数字以后本来就没办法求和回复,想要精准就用两个数存成分数形式吧
littleylv
2020-03-31 10:41:39 +08:00
想要保证 100 ?最后一个值用 100 减去前面的总和就行了
mw717if
2020-03-31 10:42:27 +08:00
@viggoc 哎 目前的解决方案是保存提高精度:实际需要小数点后两位,但是保存了四位
mw717if
2020-03-31 10:53:15 +08:00
@littleylv 精彩!!!
SjwNo1
2020-03-31 10:56:21 +08:00
@littleylv 逻辑鬼才
realpg
2020-03-31 10:59:19 +08:00
"保留两位小数"
whusnoopy
2020-03-31 11:04:33 +08:00
跟 Python 没关系啊,本来就是有精度损失的

100/3 = 33.33
100/3 = 33.33
100/3 = 33.33

33.33+33.33+33.33 = 99.99

你取多少位精度最后都会差个 1
jmc891205
2020-03-31 11:05:07 +08:00
第一 这个事情跟 Python 没关系
第二 你用一堆近似值求和得到的只会是近似值
b821025551b
2020-03-31 11:11:05 +08:00
没办法,你怎么用小数表示 1/3
hbolive
2020-03-31 11:12:07 +08:00
@mw717if 2 楼是这类情况的通用做法,可能你不太了解。。
Kakus
2020-03-31 11:12:15 +08:00
“100 减去前面总和” 要注意前面数值不能四舍五入,不然会出现最后一个比例为负值的情况。前面要用去尾方式处理。
Kakus
2020-03-31 11:15:27 +08:00
如果数据个数比较多,去尾累积误差就比较大,此时可以换成四舍五入,然后找出最大的那一条数据,误差都给他
Or2
2020-03-31 11:16:36 +08:00
Decimal(str)应该可以,Decimal(float) Decimal(double)不可以
huigeer
2020-03-31 11:16:51 +08:00
2 楼真相
sumahe
2020-03-31 11:18:40 +08:00
@littleylv 牛逼
Jooooooooo
2020-03-31 11:24:47 +08:00
相减是对的
bitdepth
2020-03-31 11:34:35 +08:00
from decimal import *
IEEE 754 了解一下
niubee1
2020-03-31 11:42:53 +08:00
基本的数学原理,分数表示的无理数没有办法用有限的小数位表示,只能近似约等,也就是丢失精度,这是初中数学学的。
melonrice
2020-03-31 11:45:38 +08:00
@niubee1 不是小学吗.....
ColinDowney
2020-03-31 11:59:56 +08:00
2 楼精彩

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/657839

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX