정도 인수와 함께 삼각 함수가 언제 -0.0을 반환해야합니까?


10

삼각 함수를 만들 때 my_sind(d), my_cosd(d), my_tand(d), 그 정도의 인수가 아닌 라디안을 사용하고 90의 배수에 정확한 답변을 제공, 나는 결과가 때로는 것을 발견 -0.0보다는 0.0.

my_sind( 0.0) -->  0.0
my_sind(-0.0) --> -0.0

my_sind(180.0) --> -0.0
my_sind(360.0) -->  0.0

sin()그리고 tan()일반적으로 주어진 기호 제로 입력에 동일한 기호 제로 결과를 반환합니다. 그것은 의미하게 my_sin()일치해야 sin()하는 입력에 있습니다.

my_sind( 0.0) alike sin( 0.0) -->  0.0
my_sind(-0.0) alike sin(-0.0) --> -0.0

문제는 : 정수가 무엇인지에 대한 non_zero_n/ 결과는 지금까지 반환 할 수 있어야 -0.0위해 my_sind(180*non_zero_n), my_cosd(180*n + 180), my_tand(180*non_zero_n)?

코드 작성이 쉬워서 코드 만 f(-0.0)작성 -0.0하고 처리 할 수 ​​있습니다. 다른 ( 0이 아닌 )에 대해 다른 f(x) 수익 -0.0을 내야 할 이유가 있는지 와 그 사인을 보장하는 것이 중요하다는 것을 궁금해합니다 .x


참고 : 이것은 왜 0.0vs. -0.0가 발생 하는지에 대한 질문이 아닙니다 . 이것이 cos(machine_pi/4)돌아 오지 않는 이유 는 아닙니다 0.0. 0.0또는 의 생성을 제어하는 ​​방법에 대한 질문도 아닙니다 -0.0. 나는 그것을 디자인 질문으로 가장 잘 본다.

답변:


4

"최소한의 놀라움"의 설계 원칙은 우리가 이전에 확립 한 기능을 참조하여 제시 함을 시사합니다. 이 경우 IEEE Std 754-2008 (부동 소수점 산술에 대한 IEEE 표준), 섹션 9에서 소개 된 기능 sinpi과 가장 가까운 기능이 제공됩니다. cospi이러한 기능은 현재 ISO C 및 ISO C ++ 표준의 일부가 아니지만 CUDA와 같은 다양한 프로그래밍 플랫폼의 수학 라이브러리에 통합되었습니다.

이 함수는 sin (πx) 및 cos (πx)를 계산합니다. 여기서 π와의 곱셈은 함수 내부에서 암시 적으로 발생합니다. tanpi수학적으로 정의 된 것은 아니지만 수학적 동등성에 기초하여에 따라 기능을 제공한다고 가정 할 수있다 tanpi(x) = sinpi(x) / cospi(x).

우리는 지금 정의 할 수 있습니다 sind(x) = sinpi(x/180), cosd(x) = cospi(x/180), tand(x) = tanpi(x/180)직관적 인 방식으로. IEEE-754의 섹션 9.1.2에서는 sinpi및에 대한 특수 인수 처리에 대해 설명 cospi합니다. 특히:

양의 정수 n에 대해 sinPi (+ n)은 +0이고 sinPi (−n)은 -0입니다. 이는 적절한 반올림 모드에서 sinPi (−x) 및 −sinPi (x)가 모든 x에 대해 동일한 수 (또는 둘 다 NaN)임을 나타냅니다. n + ½을 표현할 수있는 경우 정수 n에 대해 cosPi (n + ½)은 +0입니다.

IEEE 754-2008 표준은 인용 된 요구 사항에 대한 이론적 근거를 제공하지 않지만 관련 섹션 의 초기 초안 은 다음과 같습니다.

함수의 값이 0이면이 0의 부호는 수학 함수의 부호 함수의 연속 확장을 고려하여 가장 잘 결정됩니다.

754 Working Group Mail Archive 의 Perusal은 추가 통찰력을 얻을 수 있지만,이를 조사 할 시간이 없었습니다. 구현 sind(), cosd()tand()상술 한 바와 같이, 우리는 예를 들어 케이스의 표에 도달 :

SIND
 angle value 
  -540 -0
  -360 -0
  -180 -0
     0  0
   180  0
   360  0
   540  0

COSD
 angle value
  -630  0
  -450  0
  -270  0
   -90  0
    90  0
   270  0
   450  0

TAND
 angle value
  -540  0
  -360 -0
  -180  0
     0  0
   180 -0
   360  0
   540 -0

5

sin () 및 tan ()은 일반적으로 주어진 부호 0 입력에 대해 동일한 부호 0 결과를 반환합니다.

일반적으로 다음과 같은 이유로 사실 일 수 있습니다.

  • 속도 / 정확도 . 충분히 작은 복식의 경우 가장 좋은 대답은 sin(x)입니다 x. 즉, 약보다 작은 숫자 1.49e-8의 경우 x의 사인에 가장 가까운 double은 실제로 x 자체입니다 ( sin ()glibc 소스 코드 참조 ).

  • 특수한 경우의 취급 .

    몇 가지 특별한 산술 연산은 0의 부호에 의해 영향을받습니다. 예를 들어, "1/(+0) = +inf"하지만 "1/(-0) = -inf". 유용성을 유지하려면 부호 비트가 연속성 고려 사항에서 파생 된 규칙에 따라 특정 산술 연산을 통해 전파되어야합니다.

    sin (z) 및 tan (z)와 같은 초월 초월 함수와 그 역수 및 쌍곡선 유사체의 구현은 IEEE 표준에 의해 지정되지 않았지만 유사한 규칙을 따라야합니다. 의 구현은 의 가치와 sin(z) 의 부호를 재현 할 것으로 예상됩니다zz = ±O .

    ( 복잡한 초등 함수를위한 브랜치 컷 또는 W. Kahan 의 아무것도없는 사인 비트대한 많은 열망)

    음의 부호가있는 0은 아래에서 0에 접근하는 수학적 분석 개념을 단측 한계로 반영합니다 ( 1 / sin(x)제로의 부호는 큰 차이를 만듭니다).

편집하다

두 번째 요점을 고려하면 다음과 같이 작성 my_sind합니다.

my_sind(-0.0) is -0.0
my_sind(0.0) is 0.0

최신 C 표준 (F.10.1.6 sin및 F.10.1.7 tan인수가있는 경우, 서명 제로로 구현), 지정 것으로 ±0, 그것은 수정되지 않은 반환됩니다 .

편집 2

다른 값들에 대해서는 근사치의 문제라고 생각합니다. 주어진 M_PI<π :

0 = sin(π) < sin(M_PI)  1.2246467991473532e-16  +0.0
0 = sin(-π) > sin(-M_PI)  -1.2246467991473532e-16  -0.0
0 = sin(2*π) > sin(2*M_PI)  -2.4492935982947064e-16
0 = sin(-2*π) < sin(-2*M_PI)  2.4492935982947064e-16

따라서 my_sind180 °의 배수로 정확한 답을 제공 하면 반환 할 수 있습니다 ( +0.0또는 -0.0다른 것을 선호하는 명확한 이유는 보이지 않습니다).

경우 my_sind사용은 일부 근사 (예 : degree * M_PI / 180.0전환 식), 그것이 중요한 값을 접근하고 어떻게 고려해야합니다.


당신의 생각은 sind(180), sind(-180), sind(360), sind(-360),...어떻습니까?
chux-복원 Monica Monica

업데이트 해 주셔서 감사합니다. 어쩌면 내 게시물이 명확하지 않을 수 있습니다. 주된 질문 은 그렇지 않은 경우 my_trig(x)항상 반환 해야한다는 것 입니다 . -0.0|x|0.0
chux-복원 Monica Monica

"my_sind가 180 °의 배수로 정확한 답을 제공하면 +0.0 또는 -0.0을 반환 할 수 있습니다 (하나를 선호하는 명확한 이유는 보이지 않습니다)." 지금까지 가장 가까운 토론 포인트입니다. 나는 "최소한의 놀람의 원칙"이 항상 돌아 오는 것을 권장 +0.0하지만 -0.0어떤 상황에서 () 이외의 다른 상황에서 돌아올만한 이유가 있는지를 찾고 있다고 생각합니다 x == +/-0.0.
chux-복원 Monica Monica

@ chux :의 배수에 대해서는 180.0실제로 그 값이 주어진 상대 기계 정밀도의 값을 조사해야 한다고 생각 합니다. 즉, 해당 숫자 형식에서 다른 표현 가능한 값을 제공하는 가장 작은 증분 / 감소입니다. 그런 다음 해당 값을 실제 값과 비교하여 플러스 측 또는 마이너스 측에 속하는지 확인하십시오.
rwong

@rwong 아이디어 주셔서 감사합니다. 90.0의 배수 도는 의는 정확 sind(double degrees) 하고 cosd(double degrees)값이 반환 할 수 있습니다 -1.0, +0.0, +1.0. 이 게시물은 -0.0(sind (-0.0)을 제외하고) 반환 되어야합니다 . 참고 : 단순한 접근 방식을 사용 sind()하지 않습니다sin(x/360*M_PI) .
chux-복원 Monica Monica

3

라이브러리는 +0을 -0과 구별하지 않습니다. IEEE 754는 이러한 차이점에 대해 상당히 걱정하고 있습니다. 나는 수학의 함수를 수학적으로 표현할 수 없을 정도로 어려운 것을 발견했습니다. -PJ Plauger, 표준 C 라이브러리 , 1992, 128 페이지.

공식적으로 trig 함수는 C 표준에 따라 0의 부호를 반환해야합니다.

정의되지 않은 행동에 직면했을 때, 가장 놀랍게도의 원리 는에서 해당 함수의 행동을 복제하는 것을 제안합니다 math.h. 이것은 math.h제로의 부호에 의존하는 코드에 정확하게 버그를 도입하는 방법과 같은 냄새로 해당 기능의 동작에서 벗어나면서 정당한 냄새가납니다.


math.h+/- pi / 2 또는 +/- pi와 같은 인수가 주어지면 +/- pi / 2 등 근처에서 표현 가능한 값만 취할 수 있으므로 trig 함수는 0.0을 반환하지 않습니다 . 이 "인근"값은 0.0에 가까운 결과를 반환합니다. std 라이브러리 trig 함수 ( sin cos tan)는 모든 입력 (+/- 0.0 제외)에 대해 0.0 (또는 -0.0)을 반환하지 않지만 my_sind (), my_cosd (), my_tand ()는 0.0 (또는 -0.0)을 반환 할 수 있습니다. 복제 할 0.0 동작이 없습니다.
chux-복원 Monica Monica

@chux sin(-0.0)반환해야 할 전제 -0는 의심 스럽다. IEEE 표준의 구현 세부 사항을 삼각법 원칙으로 취급합니다. IEEE 구현에서 구현 된 두 간격의 한계로 0의 일반적인 수학적 원리가 있지만, 일반 삼각법 내에 있지 않은 추상화 수준에서 발생합니다 (따라서 삼각 함수가 반환하는 변수). 발생할 수있는 최선의 방법은 임의의 규칙을 정의 할 수 있다는 것입니다. 그러나 math.h0의 부호에 대한 비 차별성 에서 벗어날 수 있습니다 .
벤 rudgers

참고 : 나는 sin(-0.0)return을 제안하지 -0.0않지만 is는 when my_sind(x)과 일치해야합니다 . IOW : 이전 연습을 따르십시오. 또한 질문 자체가 이상 할 때 무엇을해야하는지에 관한 것입니다 ,해야 지금까지 반환 에로 등? 어쩌면 당신의 대답 / 의견이 그것을 설명 할 수도 있습니다-그러나 나는 그것을 보지 못했습니다. sin(x)x+/-0.0x != 0.0my_sind(x)-0.0my_sind(180)
chux-Reinstate Monica

@chux 동작이 정의되어 있지 않으면 정의되지 않습니다. 그것은 C의 방식입니다. Plauger 는 20 년 전에 글을 쓸 때 +0와 비교할 -0때 걱정하지 않았습니다 math.h. 차이점에 대한 당신의 고민이 어떤 문제를 해결하고 있는지는 분명하지 않습니다.
벤 rudgers

1
바라건대 sin(rad), 모든 값 에 대해 잘 구현 rad>0되고 정밀도 0.0가 불합리하므로 절대로 산출되지 않을 것입니다. [Ref] (www.csee.umbc.edu/~phatak/645/supl/Ng-ArgReduction.pdf) 그러나 값 0.0이 정확한 수학적 결과이므로 모든 배수마다 my_sind(deg)정확한 0.0(+ 또는-) 180.0가 생성됩니다. "최소 놀랍게도의 원리"는이 경우 0.0을 반환한다고 제안합니다. 이 경우에 내 질문을 -0.0돌려 주어야 합니까?
chux-복원 Monica Monica
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.