2014-10-21 3 views
1

코드를 작성했지만 잘못된 결과가 나타납니다!delphixe2 "유형 변환 오류!" 부분 결과?

Var 
    a,d:double; 
    c:currency; 
    b:integer; 
begin 
b:=10; 
c:=20.1; 
a:=30.1; 
d:=0; 

d:=a-b-c; 

Memo1.Lines.Add('a => '+FloatToStr(a)); 
Memo1.Lines.Add('b => '+FloatToStr(b)); 
Memo1.Lines.Add('c => '+FloatToStr(c)); 
Memo1.Lines.Add('d => '+FloatToStr(d)) 
end; 

결과 :

a => 30.1 
b => 10 
c => 20.1 
d => 1.4210854715202E-15 

결과는 0이되어야합니다! 이 컴파일러 유형 변환 오류입니까?

다른 방법이 있습니까? !!

답변

5

음, 여기서 가장 먼저 말할 것은 화재로 여기에서 놀고 있다는 것입니다. 동일한 내용으로 Integer, DoubleCurrency을 혼합합니다. 불합리한 혼합은, 솔직히, 문제를 요구하고 있습니다.

아직까지는 모르는 경우에 대비하여 모든 값을 나타낼 수있는 것은 아닙니다. 여기서, 소스 값은 다음

  • aDouble 입력 값 30.1이다. 이 값은 2 진 부동 소수점에서 정확하게 표현할 수 없습니다. closest Double value30.10000000000000142108547152020037174224853515625입니다.
  • bInteger, 값은 10입니다. 여기에 놀라움이 없습니다.
  • cCurrency이고 값은 20.1입니다. 이것은 값이 201000 인 64 비트 정수로 표시됩니다. 이것은 고정 소수점 10 진 데이터 유형입니다. 표현에는 10000의 내재적 시프트가 포함됩니다.

다음 표현식은 a - b - c입니다. 왼쪽에서 오른쪽으로 평가됩니다.

86 아래의 코드 내 주석으로, 다음과 같습니다

 
// load b into the floating point unit, converting from 32 bit integer 
fild dword ptr [$00423ef0] 
// subtract b from a, as floating point 
fsubr qword ptr [$00423ed8] 
// multiply by 10000 to convert to currency 
fmul dword ptr [$0041c5e0] 
// load c into the floating point unit, converting from 64 bit integer 
fild qword ptr [$00423ee8] 
// subtract c from (b - a) 
fsubp st(1) 
// divide by 10000, that is convert the result to a floating point value 
fdiv dword ptr [$0041c5e0] 
// store this floating point value into d 
fstp qword ptr [$00423ee0] 

우리가 d에 다시 저장 값은 0이 아닌. 본질적으로 그 이유는 (a - b)*10000 <> 20100입니다. 이제 (a - b)*10000 <> 20100을 알면 놀랄 것입니다. 그러나 위의 첫 번째 글 머리 기호에서 알 수 있듯이 a30.1의 정확한 표현이 아닙니다.

이야기의 도덕은 같은 표현에서 이진수와 십진법 피연산자를 섞어서는 안된다고 생각합니다. 적어도 그렇게 할 필요가 있다면, 어떻게하는지에 대해 명확하고 정확해야합니다. 예를 들어.

따라서 계산을 모두 Currency으로 수행하면 예상 한 답변을 얻을 수 있습니다. Currency은 10 진수 표현이며 이러한 모든 값과 모든 중간 값을 정확하게 저장할 수 있기 때문입니다.

+0

double type 변수 "30.1"실제로 값 "30.10000000000000142108547152020037174224853515625"를 받는다는 것은 놀라운 가치입니다! 논리적으로 나는 타입 변환을 할 필요가없는 방식으로 이해할 수 있는가? –

+0

무슨 뜻인지 모르겠다. 도움이 더 필요하십니까? –

+1

나는 OP가 [모든 컴퓨터 과학자가 부동 소수점 산술에 관해 알아야 할 내용] (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html)을 살펴보고 싶다고 생각합니다. –

0
Var 
     a,d:double; 
     c:double; 
     b:double; 
    begin 
    b:=10; 
    c:=20.1; 
    a:=30.1; 
    d:=0; 

    d:=a-b-c; 

    Memo1.Lines.Add('a => '+FloatToStr(a)); 
    Memo1.Lines.Add('b => '+FloatToStr(b)); 
    Memo1.Lines.Add('c => '+FloatToStr(c)); 
    Memo1.Lines.Add('d => '+FloatToStr(d)) 
    end; 

결과 :

a => 30.1 
b => 10 
c => 20.1 
d => 0 

같은 유형의 변수를 개선하는 문제!

우리가 오류를 계속 사용할 경우 다른 유형 (통화)의 값을 지정할 때 "이중"유형이 계속됩니다.