태그 보관물: c

c

정도 인수와 함께 삼각 함수가 언제 -0.0을 반환해야합니까? 정도의 인수가 아닌 라디안을 사용하고 90의

삼각 함수를 만들 때 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. 나는 그것을 디자인 질문으로 가장 잘 본다.



답변

“최소한의 놀라움”의 설계 원칙은 우리가 이전에 확립 한 기능을 참조하여 제시 함을 시사합니다. 이 경우 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


답변

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전환 식), 그것이 중요한 값을 접근하고 어떻게 고려해야합니다.


답변

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

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

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


답변