首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么Python没有sign函数?

为什么Python没有sign函数?
EN

Stack Overflow用户
提问于 2010-01-01 00:56:41
回答 13查看 196.4K关注 0票数 293

我不明白为什么Python没有sign函数。它有一个内置的abs (我认为它是sign的姊妹),但没有sign

在Python2.6中,甚至有一个copysign函数(在math中),但是没有符号。既然只需编写copysign(x,y),然后直接从abs(x) * sign(y)获取copysign,为什么还要费心编写sign呢?后者会更清楚:x的符号是y,而使用copysign时,你必须记住是x的符号是y,还是y的符号是x!

显然,除了cmp(x,0)之外,sign(x)并没有提供更多的东西,但它的可读性也会更好(对于像python这样可读性很强的语言来说,这将是一个很大的优势)。

如果我是一个python设计者,我会是另一种方式:没有cmp内置,而是一个sign。当你需要cmp(x,y)时,你可以只做一个sign(x-y) (或者,对于非数字的东西,更好的是,只做一个x>y -当然这应该要求sorted接受一个布尔值而不是整数比较器)。这也会更清楚:当x>y时为正(而对于cmp,当first更大时,您必须记住约定为正,但也可能是相反的情况)。当然,出于其他原因,cmp本身也是有意义的(例如,当对非数字对象进行排序时,或者如果您希望排序是稳定的,而这不可能简单地与布尔值一起使用)。

因此,问题是:为什么Python设计者决定将sign函数排除在语言之外?为什么要为copysign而不是它的父sign而烦恼呢

我是不是遗漏了什么?

编辑-在Peter Hansen评论之后。你没有使用它是合理的,但是你没有说你使用python做什么。在我使用python的7年中,我无数次地需要它,最后一次是压垮了骆驼的稻草!

是的,你可以到处传递cmp,但我需要传递它的90%的次数是在像lambda x,y: cmp(score(x),score(y))这样的习惯用法中,它可以很好地与sign一起工作。

最后,我希望您同意sign将比copysign更有用,所以即使我同意您的观点,为什么还要费心在数学中定义它,而不是符号呢?为什么版权签名比签名更有用呢?

EN

回答 13

Stack Overflow用户

回答已采纳

发布于 2010-01-01 03:25:01

编辑:

确实有一个patchmath中包含了sign(),但它没有被接受,因为他们在what it should return in all the edge cases (+/-0,+/-nan等)上没有达成一致。

因此他们决定只实现copysign,它(虽然更冗长)可以是used to delegate to the end user the desired behavior for edge cases - they sometimes might require the call to cmp(x,0)

我不知道为什么它不是内置的,但我有一些想法。

代码语言:javascript
运行
复制
copysign(x,y):
Return x with the sign of y.

最重要的是,copysignsign的超集!使用x=1调用copysignsign函数相同。所以你可以直接使用copysign,然后忘掉它。

代码语言:javascript
运行
复制
>>> math.copysign(1, -4)
-1.0
>>> math.copysign(1, 3)
1.0

如果你厌倦了传递两个完整的参数,你可以用这种方式实现sign,而且它仍然与其他人提到的IEEE兼容:

代码语言:javascript
运行
复制
>>> sign = functools.partial(math.copysign, 1) # either of these
>>> sign = lambda x: math.copysign(1, x) # two will work
>>> sign(-4)
-1.0
>>> sign(3)
1.0
>>> sign(0)
1.0
>>> sign(-0.0)
-1.0
>>> sign(float('nan'))
-1.0

其次,通常当你想要某个东西的符号时,你只需将它与另一个值相乘。当然,这基本上就是copysign所做的。

因此,不是:

代码语言:javascript
运行
复制
s = sign(a)
b = b * s

你可以这样做:

代码语言:javascript
运行
复制
b = copysign(b, a)

是的,我很惊讶你已经使用Python7年了,并且认为cmp可以如此容易地被sign移除并取代!您是否从未使用__cmp__方法实现过类?您是否从未调用过cmp并指定了自定义比较器函数?

总之,我发现自己也需要一个sign函数,但是第一个参数为1的copysign就可以很好地工作了。我不同意sign会比copysign更有用的说法,因为我已经证明了它只是相同功能的一个子集。

票数 275
EN

Stack Overflow用户

发布于 2010-01-01 03:12:12

“版权签名”是由IEEE754定义的,是C99规范的一部分。这就是它为什么用Python编写的原因。该函数不能完全由abs(x) * NaN (Y)实现,因为它应该如何处理符号的值。

代码语言:javascript
运行
复制
>>> 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()更有用的函数。

至于IEEE的signbit(x)在标准Python中不可用的具体原因,我不知道。我可以做一些假设,但这只是猜测。

数学模块本身使用copysign(1,x)作为检查x是负数还是非负数的一种方法。对于大多数情况,处理数学函数似乎比使用返回1、0或-1的符号(X)更有用,因为需要考虑的情况少了一种。例如,以下代码来自Python的数学模块:

代码语言:javascript
运行
复制
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()内置,而是一个符号()

这意味着您不知道cmp()除了用于数字之外还有其他用途。cmp("This","That")不能用sign()函数实现。

用于整理我在其他地方的其他答案的编辑

您的理由是abs()和sign()经常被放在一起看。由于C标准库不包含任何类型的“sign(X)”函数,我不知道您如何证明您的观点是正确的。有abs(整型)、fabs(双精度)、fabsf(浮点型)和fabsl(长型),但没有提到符号。有"copysign()“和"signbit()”,但它们只适用于IEEE754号。

对于复数,sign(-3+4j)在Python语言中会返回什么,要实现它吗?abs(-3+4j)回报率为5.0.这是一个清楚的例子,说明了如何在sign()没有意义的地方使用abs()。

假设将sign(x)添加到Python中,作为abs(x)的补充。如果'x‘是实现__abs__(self)方法的用户定义类的实例,则abs(x)将调用x.__abs__()。为了正确地工作,要以同样的方式处理abs(x),那么Python将不得不获得一个sign(x)插槽。

对于相对不需要的函数来说,这是多余的。此外,为什么符号(X)存在而非负(X)和非正(X)不存在?我的Python数学模块实现片段展示了如何使用copybit(x,y)来实现非负(),这是简单的符号(X)所不能做到的。

Python应该支持对IEEE754/C99数学函数有更好的支持。这将添加一个signbit(x)函数,它将在浮点数的情况下执行您想要的操作。它不适用于整数或复数,更不用说字符串了,而且它也不会有您想要的名称。

你问“为什么”,答案是"sign(x)没有用“。你断言它是有用的。然而,你的评论表明,你知道的还不足以做出这样的断言,这意味着你必须拿出令人信服的证据来证明它的必要性。说NumPy实现了它是不够令人信服的。您需要展示如何使用sign函数改进现有代码的案例。

而且它超出了StackOverflow的范围。取而代之的是其中一个Python列表。

票数 68
EN

Stack Overflow用户

发布于 2013-05-24 09:37:40

sign()的另一行代码

代码语言:javascript
运行
复制
sign = lambda x: (1, -1)[x<0]

如果您希望x=0时返回0:

代码语言:javascript
运行
复制
sign = lambda x: x and (1, -1)[x<0]
票数 44
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1986152

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档