2009-06-24 10 views
13

수학적인 이유로 정의되지 않은 값에 IEEE754 부동 소수점 NaN (숫자가 아님)을 사용하는 것이 좋습니다.설정되지 않은 값에 IEEE754 부동 소수점 NaN을 사용하는 것이 좋습니다.

우리의 경우 다른 장치에서 값을받지 못했기 때문에 아직 설정되지 않았습니다. 컨텍스트는 IEC1131 REAL32 값을 사용하는 임베디드 시스템입니다. 편집 : 프로그래밍 언어는 C이므로 C99의 NAN과 isnanf (x)를 사용합니다. 이들을 우리의 OS 호환성 레이어에 넣기 위해 약간의 왜곡이 필요할 수도 있습니다.

프로그래밍 언어의 기본값은 내부 표현이 모두 0 인 양수 0으로 부동 소수점 변수를 초기화하는 것으로 보입니다. 0은 유효한 값의 범위에 있기 때문에 우리에게는 유용하지 않습니다.

NaN을 사용하는 것은 깨끗한 솔루션처럼 보이지만 가치가있는 것보다 더 번거롭고 다른 값을 선택해야할까요?

+0

nullable 유형이 나오기 전에 .NET 1.1에서 많은 사람들이 최소값 (int.MinValue)과 같은 것을 사용했습니다. 이 문제는 모든 곳에서 그것을 고려해야하며 MinValue를 절대 사용하지 않아야한다는 것입니다. 아마도 그 라인을 따라 뭔가 C에 존재 하는가? – RichardOD

+1

나는 비슷한 (그러나 같지 않은) 질문을했다. 아마 answeres가 도움이 될 수도있다. http://stackoverflow.com/questions/787828/nan-as-a-special-argument – quinmars

답변

10

방금이 질문에 주목했습니다.

이것은 IEEE 754위원회가 염두에두고있는 NaN의 사용법 중 하나입니다 (저는위원회 위원이었습니다). 산술에서 NaN에 대한 전파 규칙은 매우 매력적인 데, 초기화 된 일부 데이터가 포함 된 긴 계산 시퀀스의 결과가있는 경우 올바른 결과를 위해 실수를하지 않기 때문입니다. 또한 계산을 통해 추적을 수행하여 초기화 된 데이터를 훨씬 쉽게 직접 사용할 수 있습니다.

즉, 754위원회의 통제 범위를 벗어나는 몇 가지 함정이 있습니다. 다른 하드웨어에서 언급했듯이 모든 하드웨어가 속도에 따라 NaN 값을 지원하지 못하기 때문에 성능 위험이 발생할 수 있습니다. 다행스럽게도 성능에 중요한 설정에서 초기화 된 데이터에 대해 많은 작업을 수행하지는 않습니다.

+0

이 경우 undefined에 대해 NaN을 사용했기 때문에 허용되었지만 예상보다 많은 번거 로움이있었습니다. 이는 도구와 시스템에서 NaN 지원이 누락되었거나 버그가 있었기 때문에 발생했습니다. 우리는이를 해결해야했습니다. – starblue

3

비슷한 상황에서 NaN을 사용했습니다. 일반적인 기본 초기화 값인 0 또한 유효한 값입니다. NaN은 지금까지 잘 작동합니다.

기본 초기화 값이 일반적으로 (예 : Java 원시 유형에서) 0이고 NaN이 아닌 것은 좋은 질문입니다. 42 살이나 됐든간에 뭐? 제로의 근거가 무엇인지 궁금하네요.

+1

0을 사용하는 이유는 메모리가 유형에 관계없이 0 바이트로 초기화된다고 생각합니다. 예를 들어 C의 BSS 세그먼트 . – starblue

+0

네, 아마도 그렇게 될 것입니다.그러나 이제는 언어/컴파일러 디자이너가 메모리를 초기화하기 위해 노력 했으므로 임의의 값 (0 이외)으로 초기화하는 것이 거의 쉽지 않을까요? 제로는 다른 것들과 조금 다릅니다 :-) –

+2

@ mad-j : 같은 비트 패턴으로 모든 메모리를 초기화하고 싶습니다. 그래서 그것은 42가 될 수 없습니다. 왜냐하면 보통 int에 대해하는 것보다 인접한 두 단락에 대해 다른 것을해야하기 때문입니다. 0과 -1이 남습니다. 하지만 0xffffffff는 부동 소수점으로 -1이 아니므로 거기에 일관성이 없습니다. 그다지 그다지 많지는 않지만, 0이 아마도 가장 좋다고 생각합니다. 또한 일부 하드웨어는 물리적 메모리의 전체 블록을 효율적으로 0 번에 처리 할 수있어 그만한 가치가 있습니다. –

0

장치가 아마도 NaN을 반환하지 않는다고 보장한다면 과 같이 장치에서받은 숫자를 나타내지 않는 부동 소수점 값을 기본 필요로하는 경우 나를.

그냥 환경에 따라, 당신은 아마하는 NaN를 검출하는 특별한 방법이 필요하다는 것을 기억 (단지 if (x == float.NaN)를 사용하지 않는 또는 상응하는 무엇이든.)

+0

이 대답을 믿지 마십시오. Jon Skeet이해야 할 일은 변수에 대해 생각하고 스스로 정의하는 것입니다. –

+0

값은 변수 이름의 Skeet보다 먼저 정의됩니다. 맞습니까? – glasnt

4

NaN을이 '값없이'에 대한 합리적인 선택입니다 sentential합니다 (D 프로그래밍 언어는 예를 들어, 초기화되지 않은 값을 사용), 그러나 그와 관련된 모든 비교가 거짓되기 때문에, 당신은 몇 놀라움 얻을 수 있습니다 : DEFAULT_VALUE 경우 예상대로 작동하지 않습니다

  • if (result == DEFAULT_VALUE) Jon이 말했듯이 NaN입니다.

  • 조심하지 않으면 범위 검사에 문제가 발생할 수도 있습니다. 기능을 고려

    x가 NaN의 경우
 
bool isOutsideRange(double x, double minValue, double maxValue) 
{ 
    return x < minValue || x > maxValue; 
} 

,이 기능을 잘못 그 x는 MINVALUE 및 maxValue를 사이에보고 할 것입니다.

사용자가 테스트 할 마법 값을 원한다면 NaN 대신 양수 또는 음수 무한대를 사용하는 것이 좋습니다. 동일한 트랩이 없기 때문입니다. NaN의 모든 연산이 NaN이되는 속성을 원할 때 NaN을 사용하십시오. 예를 들어 호출자가 값을 확인하는 데 의존하지 않으려 고 할 때 편리합니다.

[편집 : 처음에는 위에서 언급 한 "모든 비교가 참일 것입니다"라고 입력했는데, 이는 내가 의미 한 바가 아니며 잘못된 것입니다. 그들은 NaN을 제외하고 모두 거짓입니다!= NaN, true]

+0

이 비교 규칙을 사용하는 언어는 무엇입니까? 어쩌면 D가. 그러나 적어도 C와 C++은 이런 식으로 NaN과 작동하지 않습니다. 모든 순서 비교는 거짓입니다. x == NaN은 NaN을 포함하여 모든 x에 대해 거짓입니다. –

+1

아니요, 함수가 범위 밖에 있음을보고합니다. 내부 또는 외부가 아니기 때문에 실수로 부동 소수점 숫자를 사용하는 사람들을 혼란스럽게 할 수 있습니다. – starblue

+0

@Igor : 우리도 똑같은 말을하고 있습니다. x가 NaN의 경우는 isOutsideRange가 false를 돌려 주어, 범위 내에있는 것을 나타냅니다. – jskinner

1

감정은 조금 해킹되지만, 적어도이 NaN 값으로 연산을하면 결과가 NaN이됩니다. 버그 리포트에서 NaN을 볼 때 당신은 당신이 어떤 종류의 실수를하고 있는지 알고 있습니다.

2

주의 사항 NaN은 조심하지 않으면 산불처럼 퍼질 수 있습니다.

그들은 float에 대해 완벽하게 유효한 값이지만, 이들을 포함하는 모든 지정도 NaN과 동일하므로 코드를 통해 전파됩니다. 이것은 잡는다면 디버깅 도구로 아주 좋습니다.하지만 릴리스 할 무언가를 가져오고 어딘가에 프린지 케이스가 있다면 진짜 불쾌 할 수도 있습니다.

D는 float NaN을 기본값으로 제공하기위한 이론적 근거로 사용합니다. (어느 쪽이 동의하는지 모르겠다.)

+9

Err ... 전파 할 NaN의 포인트가 아닌가요? NaN을 결과로 가져 오는 것이 훨씬 낫습니다. 무언가 잘못되었다는 것을 나타내는 것보다 무고한 보이지만 완전히 잘못된 숫자 (실수로 초기화 된 숫자를 실수로 사용하여 발생하는 것)가있는 것입니다. –

+1

출력 결과를 보거나 NaN을 명시 적으로 확인하여 NaN 만 발견했기 때문에 예 및 아니오입니다. 결과는 오류가 발생하는 것보다 훨씬 늦게 감지 될 수 있다는 것입니다. 반면에 NULL을 사용하면 (가능한 경우) NPE/세분화 오류가 발생합니다. 잔인 하긴하지만 효율적입니다. –

+0

NaN이 어디 에나있다는 것을 아는 사람이라면, 그들이 어디에서 왔는지를 정확히 알 수는 없습니다. – corsiKa

3

나는 일반적으로 나쁜 생각이라고 생각한다. 한 가지 명심해야 할 점은 대부분의 CPU는 Nan을 "보통"플로트보다 훨씬 느리게 처리한다는 것입니다. 그리고 당신이 보통의 환경에서 결코 앤을 가질 수 없다는 것을 보장하는 것은 어렵습니다. 수치 계산에서의 나의 경험은 가치있는 것보다 더 많은 문제를 야기한다는 것입니다.

올바른 해결책은 float에 "가치 부재"를 인코딩하는 것을 피하고 다른 방법으로 신호를 보내는 것입니다. 그래도 코드베이스에 따라 실용적인 것은 아닙니다.

0

이것은 나에게 좋은 용도로 들립니다. 내가 그걸 생각해 봤으면 좋겠어.

물론, 그들은 바이러스처럼 전파되어야한다.

저는 무한 중 하나 대신 나노를 사용할 것이라고 생각합니다. 신호 nan을 사용하는 것이 좋을 수도 있고 처음 사용시에 이벤트를 발생시킬 수도 있지만 너무 늦으면 처음 사용할 때 조용 해져야합니다.

0

기본값으로 NaN을 사용하는 것이 좋습니다.

(0.0/0.0)과 같은 일부 표현식은 NaN을 반환합니다.