2014-02-27 12 views
2

나는 FloatToText이 방법을 사용하고 있습니다 :FloatToText가 다른 프로젝트에서 다른 값을 반환하는 이유는 무엇입니까?

나는이 함수 값 9229.99에 전달하면
function ExFloatToStr(Value: Extended): string; 
var 
    Buffer: array[0..63] of Char; 
    FormatSettings: TFormatSettings; 
begin 
    GetLocaleFormatSettings(GetUserDefaultLCID, FormatSettings); 
    SetString(Result, Buffer, FloatToText(Buffer, Value, fvExtended, ffGeneral, 
    18, 0, FormatSettings)); 
end; 

, 그것은 문자열 값 9229.9900000000016을 반환하지만, 내가 원하는 게 아니에요. 새 프로젝트를 만들고 거기에있는 코드를 복사하면 잘 작동합니다. 9229.99를 반환합니다.

다른 프로젝트에서 서로 다른 점은 무엇일까요?

+0

표현 가능성 문제를 이해하고 있습니까? –

+0

@David 두 개의 프로젝트에서 OP가 동일한 (!) 부동 소수점 숫자를 사용했지만 다른 결과를 얻었 기 때문에 표현 가능성이 여기에 문제가되는 것은 의심 스럽습니다. – iamjoosy

+0

@iamjoosy 예,하지만 사용자가 '9229.99'를 이진 부동 소수점으로 표현할 수 없다는 것을 알았는지 여부를 확인하려고합니다. –

답변

5

사실 이것은 표현의 문제입니다.

{$APPTYPE CONSOLE} 

uses 
    SysUtils, Windows; 

function ExFloatToStr(Value: Extended): string; 
var 
    Buffer: array[0..63] of Char; 
    FormatSettings: TFormatSettings; 
begin 
    GetLocaleFormatSettings(GetUserDefaultLCID, FormatSettings); 
    SetString(Result, Buffer, FloatToText(Buffer, Value, fvExtended, ffGeneral, 
    18, 0, FormatSettings)); 
end; 

var 
    X: Double; 
    Y: Extended; 

begin 
    X := 9229.99; 
    Y := 9229.99; 
    Writeln(ExFloatToStr(X)); 
    Writeln(ExFloatToStr(Y)); 
    Readln; 
end. 

출력 당신은 18 자리를 요구

 
9229.98999999999978 
9229.99 

: 여기 SSCCE입니다. 값을 배정 밀도로 저장하면 저장된 값은 십진수 십진수의 정밀도로 부정확 해집니다. 배정도 값의 정밀도는 십진수 십진수로 15-16 자릿수입니다. 그리고 그 값은 18보다 적습니다. 값을 확장 된 값으로 저장하면 더 정밀하게 사용할 수 있으므로 요청한 정밀도 18 자리에 정확하게 값을 저장할 수 있습니다.

난 항상이 문제에 롭 케네디의 우수한 페이지를 참조

: http://pages.cs.wisc.edu/~rkennedy/exact-float?number=9229.99

이 확장 된 더블로 변환하여 값이 표시되는 것을 우리에게 알려줍니다 같은 :

 
9229.99 = + 9229.99000 00000 00000 21316 28207 28030 05576 13372 80273 4375 
9229.99 = + 9229.98999 99999 99781 72127 15744 97222 90039 0625 

그리고이와 정확하게 연산하고 위의 출력.

그래서 저는 기존 프로젝트에서 어느 시점에 배정 밀도 변수에 값을 저장하게 될 것으로 기대합니다. 그리고 그 시점에서 Extended의 추가 정밀도를 잃게됩니다.

80 비트 확장형은 시대 착오적 인 것으로 간주됩니다. 인텔 칩에서만 지원되며 32 비트 컴파일러에서만 사용됩니다. 내 경험에 의하면 nevers는 배정도 이상의 실질적인 이점을 제공합니다. 메모리 정렬 때문에 성능이 떨어집니다. 많은 부동 소수점 코드의 작성자로서 나는 결코 확장을 사용하지 않습니다.

+1

부동 소수점 숫자의 정확한 표현을위한 소스를 찾을 수 있습니다 : ['Exterior Float to String Routines'] (http://cc.embarcadero.com/Item/19421). 존 허 스터 글 –

+0

@LURD Rob의 코드는 C 언어로 작성되었습니다. –

+1

@RobKennedy의 불신을 의미하지는 않습니다. 문자열 변환에 대한 정확한 플로트를 생성하는 델파이 코드 링크를 제공하십시오. –

2

x86 대 x64 Windows 대상에 대해 컴파일 할 때 차이가 있습니다.

x86 플랫폼의 경우 '확장형'유형은 x64 플랫폼에서 '크기'가 다릅니다. 당신은 텍스트 값에 다른 변환이 발생할 수 있습니다 덜 중요한 부동 소수점 값을 가지고,

System.Extended offers greater precision than other real types, but is less 
portable. Be careful using System.Extended if you are creating data files to 
share across platforms. 

On Win32 systems, the size of System.Extended is 10 bytes. 

On Win64 systems, however, the System.Extended type is an alias for System.Double, 
which is only 8 bytes. This difference can adversely affect numeric precision in 
floating-point operations. For more information, see Delphi Considerations for 
Cross-Platform Applications. 

Writeln(IntToStr(SizeOf(Extended))); // displays 10 on Win32 and 8 on Win64 

기본적으로이 x64 플랫폼에 의미

는 델파이 도움말 (XE2)를 참조하십시오.

+0

사실이지만 문제가 될 가능성은 거의 없습니다. 결국, asker는 최소한 새로운 프로젝트에서 32 비트 코드를 실행하고 있습니다. –