[python] 왜 파이썬에는 부호 함수가 없습니까?

왜 파이썬에 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! copysignx = 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커스텀 비교기 함수를 호출 하고 지정한 적이 있습니까?

요약하면, 나는 나 자신 sign도 함수를 원한다는 것을 알았지 만 copysign첫 번째 인수가 1이면 잘 작동합니다. 나는 그것이 동일한 기능의 하위 집합이라는 것을 보여 주었기 sign때문에보다 유용하다고 동의하지 copysign않습니다.


답변

“copysign”은 IEEE 754 및 C99 사양의 일부로 정의됩니다. 그것이 파이썬에있는 이유입니다. NaN 값을 처리하는 방식 때문에 abs (x) * sign (y)로 함수를 완전히 구현할 수 없습니다.

>>> 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)를 표준 파이썬에서 사용할 수없는 특정 이유에 대해서는 모르겠습니다. 나는 가정을 할 수 있지만 추측 할 것입니다.

수학 모듈 자체는 x가 음수인지 음수가 아닌지 확인하는 방법으로 copysign (1, x)을 사용합니다. 고려해야 할 경우가 적기 때문에 1, 0 또는 -1을 반환하는 sign (x)보다 더 유용한 수학 함수를 다루는 대부분의 경우. 예를 들어 다음은 Python의 수학 모듈에서 가져온 것입니다.

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 ()이 3 값 sign () 함수보다 더 효과적인 함수임을 분명히 알 수 있습니다.

당신은 썼습니다 :

파이썬 디자이너라면 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) 반환되는 것은 무엇입니까? abs (-3 + 4j)는 5.0을 반환합니다. sign ()이 의미가없는 곳에서 abs ()를 사용하는 방법에 대한 명확한 예입니다.

abs (x)의 보완으로 sign (x)가 Python에 추가되었다고 가정합니다. ‘x’가 __abs __ (self) 메소드를 구현하는 사용자 정의 클래스의 인스턴스 인 경우 abs (x)는 x .__ abs __ ()를 호출합니다. 올바르게 작동하려면 동일한 방식으로 abs (x)를 처리하려면 파이썬이 부호 (x) 슬롯을 가져와야합니다.

상대적으로 필요하지 않은 기능에는 과도합니다. 게다가 sign (x)가 존재하고 nonnegative (x)와 nonpositive (x)가 존재하지 않는 이유는 무엇입니까? 파이썬의 수학 모듈 구현에서 내 스 니펫은 copybit (x, y)를 사용하여 간단한 부호 (x)가 할 수없는 음이 아닌 ()을 구현하는 방법을 보여줍니다.

파이썬은 IEEE 754 / C99 수학 함수를 더 잘 지원해야합니다. 부동 소수점의 경우 원하는 것을 수행하는 signbit (x) 함수가 추가됩니다. 정수 또는 복소수, 훨씬 적은 문자열에서는 작동하지 않으며 찾고있는 이름이 없습니다.

“왜”를 물어 보면 “sign (x)는 쓸모가 없습니다.” 당신은 그것이 유용하다고 주장합니다. 그러나 당신의 의견은 당신이 그 주장을 할 수있을만큼 충분히 알지 못한다는 것을 보여줍니다. NumPy가 구현한다고 말하면 충분하지 않습니다. 부호 함수를 사용하여 기존 코드를 개선하는 방법을 보여 주어야합니다.

그리고 그것은 StackOverflow의 범위를 벗어났습니다. 대신 파이썬 목록 중 하나로 가져 가십시오.


답변

sign ()을위한 또 하나의 라이너

sign = lambda x: (1, -1)[x<0]

x = 0에 대해 0을 반환하려면 다음을 수행하십시오.

sign = lambda x: x and (1, -1)[x<0]


답변

이후 cmp되었습니다 제거 , 당신과 같은 기능을 얻을 수 있습니다

def cmp(a, b):
    return (a > b) - (a < b)

def sign(a):
    return (a > 0) - (a < 0)

그것은 작동 float, int심지어 Fraction. 의 경우 float통지 sign(float("nan"))는 0입니다.

파이썬은 비교가 부울을 반환하도록 요구하지 않으므로 bool ()에 비교를 강제하면 허용되지만 드물게 구현되는 것을 방지합니다.

def sign(a):
    return bool(a > 0) - bool(a < 0)


답변

Wikipedia 정의를 준수하는 정답 만

Wikipedia에 대한 정의는 다음과 같습니다.

부호 정의

그 후,

sign = lambda x: -1 if x < 0 else (1 if x > 0 else (0 if x == 0 else NaN))

모든 의도와 목적을 위해 다음과 같이 단순화 할 수 있습니다.

sign = lambda x: -1 if x < 0 else (1 if x > 0 else 0)

이 기능 정의 빨리 실행하는 수율은 보장 , 0 올바른 결과를 0.0, -0.0, -4, 5 (다른 잘못된 답변에 의견을 참조).

참고 제로 (0)가도 긍정적이나 부정적인이다 .


답변

numpy에는 부호 기능이 있으며 다른 기능도 제공합니다. 그래서:

import numpy as np
x = np.sign(y)

결과가 numpy.float64인지주의하십시오.

>>> type(np.sign(1.0))
<type 'numpy.float64'>

json은 numpy.float64 유형을 직렬화하는 방법을 모르기 때문에 json과 같은 것이 중요합니다. 이 경우 다음을 수행 할 수 있습니다.

float(np.sign(y))

정기적 인 플로트를 얻습니다.


답변

여기서 x는 숫자입니다.

int_sign = bool(x > 0) - bool(x < 0)

bool ()에 대한 강제 는 비교 연산자가 부울을 리턴하지 않을 가능성 을 처리합니다 .