9

그래서 내가 이렇게 보이는 기능이 있습니다 어떤 시점에서어떻게 든 변수를 변경할 수 있습니까?

float function(){ 
    float x = SomeValue; 
    return x/SomeOtherValue; 
} 

,이 기능 오버 플로우와 정말 큰 음의 값을 반환합니다. 이 위치가 정확히 어디에서 발생했는지 추적하기 위해이 함수가 다음과 같이 보이도록 명령문을 추가했습니다.

! 물론, 나는 double을 사용하여 문제를 모두 해결했다. 하지만 필자가 그것을 요구할 때 함수가 제대로 작동하는 이유에 대해 궁금합니다. 이게 전형적인가요, 아니면 제가 누락 된 다른 곳의 버그가있을 수 있습니까?

(그것이 어떤 도움이 있다면, 플로트에 저장되어있는 값은 단지 정수 값, 그리고 특히 큰 하나가. 난 그냥 캐스팅을 피하기 위해 플로트에 넣어.)

답변

18

놀라운 부동 소수점 세계에 오신 것을 환영합니다. 얻을 수있는 대답은 코드를 컴파일 한 부동 소수점 모델에 따라 달라질 수 있습니다.

이는 IEEE 사양과 코드가 실행되는 하드웨어의 차이로 인해 발생합니다. CPU에는 32 비트 부동 소수점 값을 유지하는 데 사용되는 80 비트 부동 소수점 레지스터가있을 가능성이 큽니다. 즉, 값이 메모리 주소 (레지스터의 '원점 복귀'라고도 함)로 강제로 전달되는 경우보다 값이 레지스터에 머무르는 동안 훨씬 더 정밀도가 높아집니다.

이 값을 cout에 전달하면 컴파일러에서 부동 소수점을 메모리에 씁니다. 결과적으로 WRT 오버플로의 경우 정확하고 흥미로운 동작이 손실됩니다.

VC++ floating point switches에 대한 MSDN 설명서를 참조하십시오./fp : strict로 컴파일을 시도하고 어떤 일이 일어나는 지 볼 수 있습니다. 이 실수로 함수에 변수를 전달하지 못할 것입니다 무엇보다도

float function(){ 
    const float x = SomeValue; 
    cout << x; 
    return x/SomeOtherValue; 
} 

을 비 const 참조를 통해 수정할 수 : 여담으로

+0

http://gcc.gnu.org/wiki/x87note에서도 GCC 노트가 있습니다. 부동 소수점 계산을 비교하는 것은 사전 계산 값을 사용하지 않는 한 본질적으로 손상됩니다. – hazzen

3

값을 인쇄하기를 법원하기 매개 변수의 값을 어떤 식 으로든 변경해서는 안됩니다.

그러나 디버깅 문을 추가하면 값이 변경되는 유사한 동작이 나타납니다. 이러한 경우에는 아마 추측 할 수 있겠지만 추가 계산서가 컴파일러의 옵티마이 저가 다른 방식으로 동작하게하여 함수에 대해 다른 코드를 생성 할 것입니다.

cout 문을 추가하면 x의 값이 직접 사용됩니다. 이를 사용하지 않으면 옵티마이 저가 변수를 제거하여 계산 순서를 변경하고 따라서 답을 바꿀 수 있습니다.

0

나는 그 사람이 변수에 어떤 영향을 미쳤다고 생각하지 않는다. 문제는 다른 곳에 있어야 할 것이다.

2

, 그것은 const를 사용하여 불변 변수를 선언하는 것이 좋은 생각 .

1

cout은 변수에 대한 참조를 발생시켜 컴파일러가 스택에 강제로 유출되도록합니다.

float이기 때문에 일반적으로 두 배 또는 긴 double 표현에서 값이 잘립니다.

포인터 나 참조를 취하는 모든 함수 (비 인라인)를 호출하면 동일한 문제가 발생하지만 나중에 컴파일러가 더 똑똑 해지고 인라인으로 배울 경우 균등하게 처리됩니다.