So I've decided to try to solve my physics homework by writing some python scripts to solve problems for me. One problem that I'm running into is that significant figures don't always seem to come out properly. For example this handles significant figures properly:
所以我决定尝试通过编写一些python脚本为我解决问题来解决我的物理作业。我遇到的一个问题是,有效的数字似乎并不总是正确的。例如,它可以正确处理重要数字:
from decimal import Decimal
>>> Decimal('1.0') + Decimal('2.0')
Decimal("3.0")
But this doesn't:
但这不是:
>>> Decimal('1.00') / Decimal('3.00')
Decimal("0.3333333333333333333333333333")
So two questions:
所以有两个问题:
- Am I right that this isn't the expected amount of significant digits, or do I need to brush up on significant digit math?
- Is there any way to do this without having to set the decimal precision manually? Granted, I'm sure I can use numpy to do this, but I just want to know if there's a way to do this with the decimal module out of curiosity.
我是对的,这不是预期的有效数字量,还是我需要刷数字数字?
有没有办法做到这一点,而无需手动设置小数精度?当然,我确信我可以使用numpy来做到这一点,但我只是想知道是否有办法用十进制模块出于好奇而做到这一点。
6 个解决方案
#1
8
Changing the decimal working precision to 2 digits is not a good idea, unless you absolutely only are going to perform a single operation.
将十进制工作精度更改为2位数不是一个好主意,除非您绝对只执行单个操作。
You should always perform calculations at higher precision than the level of significance, and only round the final result. If you perform a long sequence of calculations and round to the number of significant digits at each step, errors will accumulate. The decimal module doesn't know whether any particular operation is one in a long sequence, or the final result, so it assumes that it shouldn't round more than necessary. Ideally it would use infinite precision, but that is too expensive so the Python developers settled for 28 digits.
您应始终以高于重要性水平的精度执行计算,并且仅围绕最终结果。如果执行一系列长时间的计算并在每一步中舍入到有效位数,则会累积错误。十进制模块不知道任何特定操作是长序列中的一个还是最终结果,因此它假定它不应该超过必要的舍入。理想情况下它会使用无限精度,但这太贵了,因此Python开发人员确定了28位数。
Once you've arrived at the final result, what you probably want is quantize:
一旦你到达最终结果,你可能想要的是量化:
>>> (Decimal('1.00') / Decimal('3.00')).quantize(Decimal("0.001")) Decimal("0.333")
You have to keep track of significance manually. If you want automatic significance tracking, you should use interval arithmetic. There are some libraries available for Python, including pyinterval and mpmath (which supports arbitrary precision). It is also straightforward to implement interval arithmetic with the decimal library, since it supports directed rounding.
您必须手动跟踪重要性。如果要进行自动重要性跟踪,则应使用区间运算。有一些可用于Python的库,包括pyinterval和mpmath(它支持任意精度)。使用十进制库实现区间运算也很简单,因为它支持有向舍入。
You may also want to read the Decimal Arithmetic FAQ: Is the decimal arithmetic ‘significance’ arithmetic?
您可能还想阅读十进制算术常见问题解答:十进制算术“重要性”算术是什么?
#2
3
Decimals won't throw away decimal places like that. If you really want to limit precision to 2 d.p. then try
小数不会丢弃这样的小数位。如果你真的想将精度限制在2 d.p.然后试试
decimal.getcontext().prec=2
EDIT: You can alternatively call quantize() every time you multiply or divide (addition and subtraction will preserve the 2 dps).
编辑:您可以在每次乘法或除法时调用quantize()(加法和减法将保留2 dps)。
#3
1
Just out of curiosity...is it necessary to use the decimal module? Why not floating point with a significant-figures rounding of numbers when you are ready to see them? Or are you trying to keep track of the significant figures of the computation (like when you have to do an error analysis of a result, calculating the computed error as a function of the uncertainties that went into the calculation)? If you want a rounding function that rounds from the left of the number instead of the right, try:
出于好奇......是否有必要使用十进制模块?当你准备好看到它们时,为什么浮点数不会有重要的数字四舍五入?或者您是否正在尝试跟踪计算的有效数字(例如,当您必须对结果进行错误分析时,计算计算误差是计算中不确定性的函数)?如果你想要一个从数字左边而不是右边舍入的舍入函数,请尝试:
def lround(x,leadingDigits=0):
"""Return x either as 'print' would show it (the default)
or rounded to the specified digit as counted from the leftmost
non-zero digit of the number, e.g. lround(0.00326,2) --> 0.0033
"""
assert leadingDigits>=0
if leadingDigits==0:
return float(str(x)) #just give it back like 'print' would give it
return float('%.*e' % (int(leadingDigits),x)) #give it back as rounded by the %e format
The numbers will look right when you print them or convert them to strings, but if you are working at the prompt and don't explicitly print them they may look a bit strange:
当您打印它们或将它们转换为字符串时,这些数字看起来是正确的,但如果您在提示符处工作并且没有明确打印它们,它们可能看起来有点奇怪:
>>> lround(1./3.,2),str(lround(1./3.,2)),str(lround(1./3.,4))
(0.33000000000000002, '0.33', '0.3333')
#4
0
Decimal defaults to 28 places of precision.
The only way to limit the number of digits it returns is by altering the precision.
十进制默认为28个精度位置。限制返回的位数的唯一方法是改变精度。
#5
0
If I undertand Decimal correctly, the "precision" is the number of digits after the decimal point in decimal notation.
如果我正确地进行十进制,则“精度”是十进制表示法中小数点后的位数。
You seem to want something else: the number of significant digits. That is one more than the number of digits after the decimal point in scientific notation.
你似乎想要别的东西:有效位数。这比科学记数法中小数点后的位数多一个。
I would be interested in learning about a Python module that does significant-digits-aware floating point point computations.
我有兴趣了解一个Python模块,它可以进行有效数字感知的浮点计算。
#6
0
What's wrong with floating point?
浮点有什么问题?
>>> "%8.2e"% ( 1.0/3.0 )
'3.33e-01'
It was designed for scientific-style calculations with a limited number of significant digits.
它专为具有有限数字有效数字的科学计算而设计。
#1
8
Changing the decimal working precision to 2 digits is not a good idea, unless you absolutely only are going to perform a single operation.
将十进制工作精度更改为2位数不是一个好主意,除非您绝对只执行单个操作。
You should always perform calculations at higher precision than the level of significance, and only round the final result. If you perform a long sequence of calculations and round to the number of significant digits at each step, errors will accumulate. The decimal module doesn't know whether any particular operation is one in a long sequence, or the final result, so it assumes that it shouldn't round more than necessary. Ideally it would use infinite precision, but that is too expensive so the Python developers settled for 28 digits.
您应始终以高于重要性水平的精度执行计算,并且仅围绕最终结果。如果执行一系列长时间的计算并在每一步中舍入到有效位数,则会累积错误。十进制模块不知道任何特定操作是长序列中的一个还是最终结果,因此它假定它不应该超过必要的舍入。理想情况下它会使用无限精度,但这太贵了,因此Python开发人员确定了28位数。
Once you've arrived at the final result, what you probably want is quantize:
一旦你到达最终结果,你可能想要的是量化:
>>> (Decimal('1.00') / Decimal('3.00')).quantize(Decimal("0.001")) Decimal("0.333")
You have to keep track of significance manually. If you want automatic significance tracking, you should use interval arithmetic. There are some libraries available for Python, including pyinterval and mpmath (which supports arbitrary precision). It is also straightforward to implement interval arithmetic with the decimal library, since it supports directed rounding.
您必须手动跟踪重要性。如果要进行自动重要性跟踪,则应使用区间运算。有一些可用于Python的库,包括pyinterval和mpmath(它支持任意精度)。使用十进制库实现区间运算也很简单,因为它支持有向舍入。
You may also want to read the Decimal Arithmetic FAQ: Is the decimal arithmetic ‘significance’ arithmetic?
您可能还想阅读十进制算术常见问题解答:十进制算术“重要性”算术是什么?
#2
3
Decimals won't throw away decimal places like that. If you really want to limit precision to 2 d.p. then try
小数不会丢弃这样的小数位。如果你真的想将精度限制在2 d.p.然后试试
decimal.getcontext().prec=2
EDIT: You can alternatively call quantize() every time you multiply or divide (addition and subtraction will preserve the 2 dps).
编辑:您可以在每次乘法或除法时调用quantize()(加法和减法将保留2 dps)。
#3
1
Just out of curiosity...is it necessary to use the decimal module? Why not floating point with a significant-figures rounding of numbers when you are ready to see them? Or are you trying to keep track of the significant figures of the computation (like when you have to do an error analysis of a result, calculating the computed error as a function of the uncertainties that went into the calculation)? If you want a rounding function that rounds from the left of the number instead of the right, try:
出于好奇......是否有必要使用十进制模块?当你准备好看到它们时,为什么浮点数不会有重要的数字四舍五入?或者您是否正在尝试跟踪计算的有效数字(例如,当您必须对结果进行错误分析时,计算计算误差是计算中不确定性的函数)?如果你想要一个从数字左边而不是右边舍入的舍入函数,请尝试:
def lround(x,leadingDigits=0):
"""Return x either as 'print' would show it (the default)
or rounded to the specified digit as counted from the leftmost
non-zero digit of the number, e.g. lround(0.00326,2) --> 0.0033
"""
assert leadingDigits>=0
if leadingDigits==0:
return float(str(x)) #just give it back like 'print' would give it
return float('%.*e' % (int(leadingDigits),x)) #give it back as rounded by the %e format
The numbers will look right when you print them or convert them to strings, but if you are working at the prompt and don't explicitly print them they may look a bit strange:
当您打印它们或将它们转换为字符串时,这些数字看起来是正确的,但如果您在提示符处工作并且没有明确打印它们,它们可能看起来有点奇怪:
>>> lround(1./3.,2),str(lround(1./3.,2)),str(lround(1./3.,4))
(0.33000000000000002, '0.33', '0.3333')
#4
0
Decimal defaults to 28 places of precision.
The only way to limit the number of digits it returns is by altering the precision.
十进制默认为28个精度位置。限制返回的位数的唯一方法是改变精度。
#5
0
If I undertand Decimal correctly, the "precision" is the number of digits after the decimal point in decimal notation.
如果我正确地进行十进制,则“精度”是十进制表示法中小数点后的位数。
You seem to want something else: the number of significant digits. That is one more than the number of digits after the decimal point in scientific notation.
你似乎想要别的东西:有效位数。这比科学记数法中小数点后的位数多一个。
I would be interested in learning about a Python module that does significant-digits-aware floating point point computations.
我有兴趣了解一个Python模块,它可以进行有效数字感知的浮点计算。
#6
0
What's wrong with floating point?
浮点有什么问题?
>>> "%8.2e"% ( 1.0/3.0 )
'3.33e-01'
It was designed for scientific-style calculations with a limited number of significant digits.
它专为具有有限数字有效数字的科学计算而设计。