Python:一般情况下 a 可以四舍五入为 b
作为我正在编写的一些单元测试代码的一部分,我编写了以下函数。其目的是确定“a”是否可以舍入为“b”,无论“a”或“b”有多精确。
def couldRoundTo(a,b):
"""Can you round a to some number of digits, such that it equals b?"""
roundEnd = len(str(b))
if a == b:
return True
for x in range(0,roundEnd):
if round(a,x) == b:
return True
return False
这是该函数的一些输出:
>>> couldRoundTo(3.934567892987, 3.9)
True
>>> couldRoundTo(3.934567892987, 3.3)
False
>>> couldRoundTo(3.934567892987, 3.93)
True
>>> couldRoundTo(3.934567892987, 3.94)
False
据我所知,它有效。然而,考虑到我对浮点精度问题没有完全掌握,我害怕依赖它。有人可以告诉我这是否是实现此功能的合适方法?如果没有,我该如何改进?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这取决于。如果
b
不完全等于通常直接从十进制到二进制浮点转换获得的值,则给定函数的行为将会令人惊讶。例如:
此操作会失败,因为
0.3 / 3
的计算结果与0.1
和0.2 / 2
(以及圆(0.123,1))。
经验法则:如果您的计算以任何方式特别涉及十进制数字,只需使用
Decimal
即可,以避免所有有损的以 2 为基数的往返。特别是,
Decimal
包含一个名为quantize
这使得这个问题变得非常简单:It depends. The given function will behave surprisingly if
b
isn't precisely equal to a value that would normally be obtained directly from decimal-to-binary-float conversion.For example:
This fails because the calculation of
0.3 / 3
results in a slightly different representation than0.1
and0.2 / 2
(andround(0.123, 1)
).Rule of thumb: if your calculation specifically involves decimal digits in any way, just use
Decimal
, to avoid all the lossy base-2 round-tripping.In particular,
Decimal
includes a helper calledquantize
that makes this problem trivially easy:一种方法是:
首先,我们取 x 和 y 中小数点前后的位数。然后,我们构造一个诸如
%x.yf
的格式。然后,我们向格式字符串提供a
。现在,剩下的就是比较字符串了。
One way to do it:
First, we take the number of digits before and after the decimal in x and y. Then, we construct a format such as
%x.yf
. Then, we supplya
to the format string.Now, all that's left is comparing the strings.
我唯一担心的一点是在解释浮点文字时从字符串到浮点的转换(如 http://docs.python.org/reference/lexical_analysis.html#floating-point-literals)。我不知道是否可以保证浮点文字将计算为最接近给定字符串的浮点数。这个提到的部分是规范中我期望这样的保证的地方。
例如,Java 对于字符串文字的期望更加具体。来自 Double.valueOf(字符串):
除非你能找到这样的保证Python文档中的任何地方,你可能只是幸运,因为一些早期的浮点库(Python可能依赖的)将字符串仅转换为附近的浮点数,而不是最好的可用浮点数。
不幸的是,在我看来,无论是round,还是float,还是浮点文字规范都没有给你任何可用的保证。
The only point that I'm afraid of is the conversion from strings to floating points when interpreting floating-point literals (as in http://docs.python.org/reference/lexical_analysis.html#floating-point-literals). I don't know if there is any guarantee that a floating-point literal will evaluate to the floating-point number that is closest to the given string. This mentioned section is the place in the specification where I would expect such a guarantee.
For example, Java is much more specific about what to expect from a string literal. From the documentation of Double.valueOf(String):
Unless you can find such a guarantee anywhere in the Python documentation, you can be just lucky, because some earlier floating-point libraries (on which Python might rely) convert a string just to a floating-point number nearby, not to the best available.
Unfortunately, it seems to me that neither
round
, norfloat
, nor the specification for floating-point literaly give you any usable guarantee.如果您的目的是测试 round 函数是否会舍入到目标,那么您是对的。否则(还有什么目的?)如果您有疑问,您应该使用
十进制
模块If you purpose is to test if
round
function will round to the target, then you are correct. Otherwise (what else is the purpose?) if you are in doubt , you should usedecimal
module