* Fix formatfloat rounding

This commit is contained in:
michael 2018-10-27 10:56:15 +00:00
parent 972afa471d
commit 8744cbe84f

View File

@ -33,7 +33,7 @@ type
TFloatRec = Record
Exponent: Integer;
Negative: Boolean;
Digits: Array Of Char;
Digits: Array[0..18] Of Char;
End;
TEndian = (Little,Big);
TFileName = String;
@ -673,20 +673,21 @@ end;
Function FloatToDecimal(Value : double; Precision, Decimals : integer) : TFloatRec;
Const
Rounds = '234567890';
Rounds = '1234567890';
var
Buffer: String; //Though str func returns only 25 chars, this might change in the future
InfNan: string;
Error, N, L, Start, C: Integer;
OutPos,Error, N, L, Start, C: Integer;
GotNonZeroBeforeDot, BeforeDot : boolean;
begin
if Value=0 then ;
SetLength(Result.Digits,19);
if Value=0 then
exit;
asm
Buffer=Value.toPrecision(21); // Double precision
end;
// Writeln('Buffer :',Buffer);
N := 1;
L := Length(Buffer);
while Buffer[N]=' ' do
@ -714,47 +715,51 @@ begin
end;
end;
Start := N; //Start of digits
Outpos:=0;
Result.Exponent := 0; BeforeDot := true;
GotNonZeroBeforeDot := false;
while (L>=N) and (Buffer[N]<>'E') do
begin
// Writeln('Examining : ',Buffer[N],'( output pos: ',outPos,')');
if Buffer[N]='.' then
BeforeDot := false
else
begin
if BeforeDot then
begin // Currently this is always 1 char
Inc(Result.Exponent);
Result.Digits[N-Start] := Buffer[N];
if Buffer[N] <> '0' then
GotNonZeroBeforeDot := true;
end
else
Result.Digits[N-Start-1] := Buffer[N]
if BeforeDot then
begin // Currently this is always 1 char
Inc(Result.Exponent);
Result.Digits[Outpos] := Buffer[N];
if Buffer[N] <> '0' then
GotNonZeroBeforeDot := true;
end
else
Result.Digits[Outpos] := Buffer[N];
Inc(outpos);
end;
Inc(N);
end;
Inc(N); // Pass through 'E'
if N<=L then
begin
Val(Copy(Buffer, N, L-N+1), C, Error); // Get exponent after 'E'
Inc(Result.Exponent, C);
end;
// Calculate number of digits we have from str
if BeforeDot then
N := N - Start - 1
else
N := N - Start - 2;
L := Length(Result.Digits);
if N<L then
Result.Digits[N]:='0'; //Zero remaining space
if Decimals + Result.Exponent < Precision Then //After this it is the same as in FloatToDecimal
N := Decimals + Result.Exponent
Else
N := Precision;
if N >= L Then
N := L-1;
Inc(N); // Pass through 'E'
if N<=L then
begin
Val(Copy(Buffer, N, L-N+1), C, Error); // Get exponent after 'E'
Inc(Result.Exponent, C);
end;
// Calculate number of digits we have from str
N:=OutPos;
// Writeln('Number of digits: ',N,' requested precision : ',Precision);
L:=Length(Result.Digits);
While N<L do
begin
Result.Digits[N]:='0'; //Zero remaining space
Inc(N);
end;
if Decimals + Result.Exponent < Precision Then //After this it is the same as in FloatToDecimal
N := Decimals + Result.Exponent
Else
N := Precision;
if N >= L Then
N := L-1;
// Writeln('Rounding on digit : ',N);
if N = 0 Then
begin
if Result.Digits[0] >= '5' Then
@ -774,9 +779,9 @@ begin
Result.Digits[N] := #0;
Dec(N);
// Writeln(N,': ',Result.Digits[N],', Rounding to : ',Rounds[StrToInt(Result.Digits[N])]);
Result.Digits[N]:=Rounds[StrToInt(Result.Digits[N])];
Result.Digits[N]:=Rounds[StrToInt(Result.Digits[N])+1];
Until (N = 0) Or (Result.Digits[N] < ':');
If Result.Digits[0] = ':' Then
If Result.Digits[0] = '0' Then
begin
Result.Digits[0] := '1';
Inc(Result.Exponent);
@ -925,7 +930,7 @@ var
// Will return '0' if applicable.
begin
// Writeln(' DistToDecimal <= LastDigit : ',DistToDecimal,' < ',LastDigit,' have digit: ',Current<=Available, '(',Current,')');
// Writeln(' DistToDecimal <= LastDigit : ',DistToDecimal,' <= ',LastDigit,' have digit: ',Current<=Available, ' (',Current,')');
Result:=#0;
if (Current<=Available) then
begin
@ -936,7 +941,7 @@ var
Dec(DistToDecimal)
else
Result:='0';
// Writeln('GetDigit ->: ',Result);
// Writeln('GetDigit ->: ',Result);
end;
procedure CopyDigit;
@ -1112,6 +1117,9 @@ var
D:=RequestedDigits-DecimalPos+1;
end;
FV:=FloatToDecimal(aValue,P,D);
// Writeln('Number of digits available : ',Length(FV.Digits));
// For p:=0 to Length(FV.Digits)-1 do
// writeln(P,': ',FV.Digits[p]);
DistToDecimal:=DecimalPos-1;
if IsScientific then
PadZeroes:=0 // No padding.