“ copysign”由IEEE 754和C99规范的一部分定义。这就是为什么它在Python中。该函数不能完全由abs(x)* sign(y)实现,因为它应该如何处理NaN值。
>>> import math
>>> math.copysign(1, float("nan"))
1.0
>>> math.copysign(1, float("-nan"))
-1.0
>>> math.copysign(float("nan"), 1)
nan
>>> math.copysign(float("nan"), -1)
nan
>>> float("nan") * -1
nan
>>> float("nan") * 1
nan
>>>
这使copysign()比sign()更有用。
至于为什么标准的Python中没有IEEE的signbit(x)的具体原因,我不知道。我可以做一些假设,但这是猜测。
数学模块本身使用copysign(1,x)作为检查x是负数还是非负数的方法。在大多数情况下,处理数学函数似乎比使sign(x)返回1、0或-1有用,因为要考虑的情况要少得多。例如,以下内容来自Python的math模块:
static double
m_atan2(double y, double x)
{
if (Py_IS_NAN(x) || Py_IS_NAN(y))
return Py_NAN;
if (Py_IS_INFINITY(y)) {
if (Py_IS_INFINITY(x)) {
if (copysign(1., x) == 1.)
/* atan2(+-inf, +inf) == +-pi/4 */
return copysign(0.25*Py_MATH_PI, y);
else
/* atan2(+-inf, -inf) == +-pi*3/4 */
return copysign(0.75*Py_MATH_PI, y);
}
/* atan2(+-inf, x) == +-pi/2 for finite x */
return copysign(0.5*Py_MATH_PI, y);
在那里,您可以清楚地看到copysign()比三值sign()函数更有效。
你写了:
如果我是python设计器,那我将是另一种方式:没有内置的cmp(),但是有一个sign()
这意味着您不知道cmp()会用于数字以外的东西。cmp(“ This”,“ That”)不能通过sign()函数实现。
编辑以在其他地方整理我的其他答案:
您的辩解基于abs()和sign()经常一起出现的方式。由于C标准库不包含任何类型的'sign(x)'函数,因此我不知道您如何证明自己的观点。有一个abs(int)和fabs(double)和fabsf(float)和fabsl(long),但没有提及符号。有“ copysign()”和“ signbit()”,但它们仅适用于IEEE 754数字。
对于复数,如果要实现,sign(-3 + 4j)在Python中返回什么?abs(-3 + 4j)返回5.0。这是一个清晰的例子,说明在sign()毫无意义的地方如何使用abs()。
假设将sign(x)添加到Python,作为对abs(x)的补充。如果“ x”是实现__abs __(self)方法的用户定义类的实例,则abs(x)将调用x .__ abs __()。为了正常工作,以与Python相同的方式处理abs(x),Python将必须获得一个符号(x)插槽。
对于相对不需要的功能来说,这是过多的。此外,为什么应该有sign(x)而不存在nonnegative(x)和nonpositive(x)?我来自Python数学模块实现的代码片段显示了如何使用copybit(x,y)来实现nonnegative(),而简单的sign(x)无法做到这一点。
Python应该支持对IEEE 754 / C99数学函数的更好支持。这将添加一个signbit(x)函数,该函数将在浮点数的情况下实现您想要的功能。它不适用于整数或复数,更不用说字符串了,并且没有您要查找的名称。
您问“为什么”,答案是“ sign(x)没用”。您断言它很有用。然而,您的评论表明,您不足以提出该断言,这意味着您必须提供令人信服的证据来证明其必要性。说NumPy实现了它还不足以令人信服。您将需要展示如何使用符号函数改进现有代码的案例。
而且它超出了StackOverflow的范围。将其改为Python列表之一。