왜 파이썬에는 부호 함수가 없습니까?
왜 파이썬에 sign
함수 가 없는지 이해할 수 없습니다 . 그것은 abs
(내가 sign
여동생으로 간주) 내장되어 있지만 없습니다 sign
.
파이썬 2.6에는 copysign
함수 ( math )가 있지만 부호는 없습니다. 왜 copysign(x,y)
당신이 그냥 쓸 sign
수 있고 copysign
직접에서 얻을 수있을 때 쓰는 것을 귀찮게 abs(x) * sign(y)
합니까? 후자는 훨씬 더 명확합니다 : x는 y의 부호가있는 반면 copysign은 x가 y의 부호 또는 x의 부호가있는 경우 x를 기억해야합니다!
분명히 sign(x)
더 많은 것을 제공하지는 않지만 이것보다 cmp(x,0)
훨씬 더 읽기 쉽습니다 (파이썬과 같이 크게 읽을 수있는 언어의 경우 큰 이점이었습니다).
만약 내가 파이썬 디자이너라면, 다른 방법은 없을 것입니다 : cmp
내장이 아니라 a sign
. 필요할 때 (또는 숫자가 아닌 것들, x> y 만 더 잘 cmp(x,y)
할 수 있습니다 sign(x-y)
-물론 sorted
정수 비교기 대신 부울을 수락 해야합니다 ). 긍정적 인 경우 x>y
( 첫 번째 가 클cmp
때 긍정적 인 규칙을 기억해야 하지만 반대 방향 일 수 있음) 더 명확 합니다. 물론 다른 이유로 (예를 들어, 숫자가 아닌 것을 정렬 할 때 또는 정렬을 안정적으로 원할 경우 단순히 부울로 사용할 수 없음) 자체적으로 의미가 있습니다.cmp
그렇다면 문제는 왜 파이썬 디자이너가 sign
함수를 언어 에서 벗어나기로 결정 했는가하는 것입니다. 도대체 왜 copysign
부모가 sign
아닌가?
뭔가 빠졌습니까?
편집-Peter Hansen 의견 후. 당신이 그것을 사용하지 않을 정도로 공평하지만 파이썬을 무엇에 사용하는지 말하지 않았습니다. 파이썬을 사용하는 7 년 만에 수많은 시간이 필요했고 마지막은 낙타의 등을 부러 뜨린 빨대입니다!
그렇습니다. cmp를 전달할 수는 있지만 통과 해야하는 시간의 90 %는 관용구와 lambda x,y: cmp(score(x),score(y))
잘 맞았 을 것입니다.
마지막으로, 나는 당신 sign
보다 더 유용 할 것이라는 데 동의하기를 바랍니다 copysign
. 그래서 당신의 견해를 사더라도 사인 대신 수학으로 그것을 정의하는 데 왜 귀찮습니까? copysign이 sign보다 어떻게 그렇게 유용 할 수 있습니까?
편집하다:
실제로 math에 포함 된 패치 가 있었지만 모든 엣지 케이스 (+/- 0, +/- nan 등) 에서 반환해야하는 것에 동의하지 않았기 때문에 승인되지 않았습니다.sign()
그들이 구현하기로 결정 그래서에만 할 수있는 (더 자세한하지만), copysign 최종 사용자 가장자리 경우에 원하는 동작에 위임하는 데 사용 - 때로는 호출이 필요할 수 있습니다cmp(x,0)
.
왜 내장되어 있지 않은지 모르겠지만 몇 가지 생각이 있습니다.
copysign(x,y):
Return x with the sign of y.
가장 중요한 copysign
것은의 슈퍼 세트입니다 sign
! copysign
x = 1로 호출 하는 것은 sign
함수 와 같습니다 . 그래서 당신은 그것을 사용 copysign
하고 잊을 수 있습니다.
>>> math.copysign(1, -4)
-1.0
>>> math.copysign(1, 3)
1.0
두 개의 전체 인수를 전달하는 데 어려움을 겪으면 sign
이 방법을 구현할 수 있으며 다른 사람들이 언급 한 IEEE와 호환됩니다.
>>> 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
입니다.
따라서 대신 :
s = sign(a)
b = b * s
당신은 할 수 있습니다 :
b = copysign(b, a)
그리고 네, 당신이 7 년 동안 파이썬을 사용하고 있다는 사실에 놀랐고 cmp
그렇게 쉽게 제거하고 대체 할 수 있다고 생각 합니다 sign
! __cmp__
메소드를 사용 하여 클래스를 구현 한 적이 있습니까? cmp
커스텀 비교기 함수를 호출 하고 지정한 적이 있습니까?
In summary, I've found myself wanting a sign
function too, but copysign
with the first argument being 1 will work just fine. I disagree that sign
would be more useful than copysign
, as I've shown that it's merely a subset of the same functionality.
"copysign" is defined by IEEE 754, and part of the C99 specification. That's why it's in Python. The function cannot be implemented in full by abs(x) * sign(y) because of how it's supposed to handle NaN values.
>>> 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
>>>
That makes copysign() a more useful function than sign().
As to specific reasons why IEEE's signbit(x) is not available in standard Python, I don't know. I can make assumptions, but it would be guessing.
The math module itself uses signbit(1, x) as a way to check if x is negative or non-negative. For most cases dealing with mathematical functions that seems more useful than having a sign(x) which returns 1, 0, or -1 because there's one less case to consider. For example, the following is from Python's math module:
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);
There you can clearly see that copysign() is a more effective function than a three-valued sign() function.
You wrote:
If I were a python designer, I would been the other way arond: no cmp() builtin, but a sign()
That means you don't know that cmp() is used for things besides numbers. cmp("This", "That") cannot be implemented with a sign() function.
Edit to collate my additional answers elsewhere:
You base your justifications on how abs() and sign() are often seen together. As the C standard library does not contain a 'sign(x)' function of any sort, I don't know how you justify your views. There's an abs(int) and fabs(double) and fabsf(float) and fabsl(long) but no mention of sign. There is "copysign()" and "signbit()" but those only apply to IEEE 754 numbers.
With complex numbers, what would sign(-3+4j) return in Python, were it to be implemented? abs(-3+4j) return 5.0. That's a clear example of how abs() can be used in places where sign() makes no sense.
Suppose sign(x) were added to Python, as a complement to abs(x). If 'x' is an instance of a user-defined class which implements the __abs__(self) method then abs(x) will call x.__abs__(). In order to work correctly, to handle abs(x) in the same way then Python will have to gain a sign(x) slot.
This is excessive for a relatively unneeded function. Besides, why should sign(x) exist and nonnegative(x) and nonpositive(x) not exist? My snippet from Python's math module implementation shows how copybit(x, y) can be used to implement nonnegative(), which a simple sign(x) cannot do.
Python should support have better support for IEEE 754/C99 math function. That would add a signbit(x) function, which would do what you want in the case of floats. It would not work for integers or complex numbers, much less strings, and it wouldn't have the name you are looking for.
You ask "why", and the answer is "sign(x) isn't useful." You assert that it is useful. Yet your comments show that you do not know enough to be able to make that assertion, which means you would have to show convincing evidence of its need. Saying that NumPy implements it is not convincing enough. You would need to show cases of how existing code would be improved with a sign function.
And that it outside the scope of StackOverflow. Take it instead to one of the Python lists.
Another one liner for sign()
sign = lambda x: (1, -1)[x<0]
If you want it to return 0 for x = 0:
sign = lambda x: x and (1, -1)[x<0]
Since cmp
has been removed, you can get the same functionality with
def cmp(a, b):
return (a > b) - (a < b)
def sign(a):
return (a > 0) - (a < 0)
It works for float
, int
and even Fraction
. In the case of float
, notice sign(float("nan"))
is zero.
Python doesn't require that comparisons return a boolean, and so coercing the comparisons to bool() protects against allowable, but uncommon implementation:
def sign(a):
return bool(a > 0) - bool(a < 0)
Try running this, where x is any number
int_sign = bool(x > 0) - bool(x < 0)
The coercion to bool() handles the possibility that the comparison operator doesn't return a boolean.
numpy has a sign function, and gives you a bonus of other functions as well. So:
import numpy as np
x = np.sign(y)
Just be careful that the result is a numpy.float64:
>>> type(np.sign(1.0))
<type 'numpy.float64'>
For things like json, this matters, as json does not know how to serialize numpy.float64 types. In that case, you could do:
float(np.sign(y))
to get a regular float.
Only correct answer compliant with the Wikipedia definition
The definition on Wikipedia reads:
Hence,
sign = lambda x: -1 if x < 0 else (1 if x > 0 else 0)
This function definition executes fast and yields guaranteed correct results for 0, 0.0, -0.0, -4 and 5 (see comments to other incorrect answers).
Yes a correct sign()
function should be at least in the math module - as it is in numpy. Because one frequently needs it for math oriented code.
But math.copysign()
is also useful independently.
cmp()
and obj.__cmp__()
... have generally high importance independently. Not just for math oriented code. Consider comparing/sorting tuples, date objects, ...
The dev arguments at http://bugs.python.org/issue1640 regarding the omission of math.sign()
are odd, because:
- There is no separate
-NaN
sign(nan) == nan
without worry (likeexp(nan)
)sign(-0.0) == sign(0.0) == 0
without worrysign(-inf) == -1
without worry
-- as it is in numpy
In Python 2, cmp()
returns an integer: there's no requirement that the result be -1, 0, or 1, so sign(x)
is not the same as cmp(x,0)
.
In Python 3, cmp()
has been removed in favor of rich comparison. For cmp()
, Python 3 suggests this:
def cmp(a, b):
return (a > b) - (a < b)
which is fine for cmp(), but again can't be used for sign() because the comparison operators need not return booleans.
To deal with this possibility, the comparison results must be coerced to booleans:
def sign(a):
return bool(x > 0) - bool(x < 0)
This works for any type
which is totally ordered (including special values like NaN
or infinities).
You dont need one, you can just use:
If not number == 0:
sig = number/abs(number)
else:
sig = 0
The reason "sign" is not included is that if we included every useful one-liner in the list of built-in functions, Python wouldn't be easy and practical to work with anymore. If you use this function so often then why don't you do factor it out yourself? It's not like it's remotely hard or even tedious to do so.
참고URL : https://stackoverflow.com/questions/1986152/why-doesnt-python-have-a-sign-function
'Programing' 카테고리의 다른 글
Windows를위한 좋은 Valgrind 대체품이 있습니까? (0) | 2020.04.30 |
---|---|
intval과 int-`(int) X`로 캐스팅하는 데 특별한 차이점이 있습니까? (0) | 2020.04.30 |
동적 변수에서 속성을 사용할 수 있는지 테스트 (0) | 2020.04.30 |
쿼리 문자열 매개 변수 및 숨겨진 매개 변수가 포함 된 GET 양식을 제출하면 사라집니다. (0) | 2020.04.30 |
Akka Kill vs. Stop Pill 대 Poison Pill? (0) | 2020.04.30 |