为什么是sqrt(x*x+y*y)!= 数学.形(x,y)在python3.8中?

2024-04-25 01:39:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在新的python3.8上运行一些测试,发现了^{}有一个问题。从文件中:

For a two dimensional point (x, y), this is equivalent to computing the hypotenuse of a right triangle using the Pythagorean theorem, sqrt(x*x + y*y).

但是,这些在3.8中并不等同:

>>> from math import hypot, sqrt
>>> x, y = 95, 168
>>> sqrt(x*x + y*y), hypot(x, y), sqrt(x*x + y*y) == hypot(x, y)
(193.0, 193.00000000000003, False)
>>> sqrt(x*x + y*y).is_integer(), hypot(x, y).is_integer()
(True, False)

在3.7中,两种方法产生完全相同的结果("193.0",它被认为是一个整数)。在


Tags: thetofalseforisintegersqrtthis
1条回答
网友
1楼 · 发布于 2024-04-25 01:39:19

函数hypot提供了数学表达式√(x2+y2)的另一个近似值,就像浮点表达式sqrt(x*x + y*y)是同一数学表达式的近似值。在

建议使用函数hypot,因为它用非常大或很小的值解决了浮点计算sqrt(x*x + y*y)中存在的非常明显的缺陷。例如,如果x只比最大有限浮点值的平方根大一点,sqrt(x*x + y*y)总是产生{},因为x*x产生{}。在

比较:

>>> x, y = 95E200, 168E200
>>> sqrt(x*x + y*y), hypot(x, y)
(inf, 1.93e+202)
>>> z, t = 95E-200, 168E-200
>>> sqrt(z*z + t*t), hypot(z, t)
(0.0, 1.93e-198)

对于这两对(分别是非常大和非常小的)输入,hypot做得很好,而{}则是灾难性的错误。在


当原始版本sqrt(x*x + y*y)工作得相当好(当值x和{}既不是很大也不是很小)时,它可能比函数{}的精度高或低,具体取决于x和{}。它们都可以被期望产生一个与数学结果相差几微秒的结果。但由于它们是用不同方法得到的不同近似值,它们可能会有所不同(在最坏的情况下是“几个ULP”的两倍)。在

hypot(x, y)的一个典型实现是首先在必要时交换x和{},这样x具有最大的幅值,然后计算x * sqrt(1 + (y/x)*(y/x))。这解决了x*x溢出的问题。作为一个副作用,这意味着即使没有溢出,结果也与sqrt(x*x + y*y)略有不同。在

注意,当您将sqrt(x*x + y*y)应用于小整数时,sqrt(x*x + y*y)更精确是正常的:当x和{}是小整数,x*x和{},它们的和可以精确地计算为浮点值。如果这个和是整数的平方,浮点函数sqrt只能计算这个整数。简而言之,在这种情况下,尽管计算是浮点的,但从头到尾都是精确的。相比之下,上面典型的hypot实现是从计算x/y(在您的测试中,95.0/168.0)开始的,而这个结果通常不能完全表示为浮点值。第一步已经产生了一个近似值,这种近似值可能会导致最终结果错误(就像在您的测试中一样)!在


对于hypot没有标准算法:它只需要计算数学表达式√(x2+y2)的良好近似值,同时避免溢出和下溢问题。This article显示了不同的实现,并指出我提到的流行实现牺牲了准确性以避免溢出和下溢(但是本文还为hypot提供了一个浮点实现,它比{}更精确,即使在{}工作的地方也是如此)。在

相关问题 更多 >