-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathFloatHlp.pas
More file actions
135 lines (118 loc) · 4.12 KB
/
FloatHlp.pas
File metadata and controls
135 lines (118 loc) · 4.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
unit FloatHlp;
////////////////////////////////////////////////////////////////////////////////
//
// Author: Jaap Baak
// https://github.com/transportmodelling/Utils
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
interface
////////////////////////////////////////////////////////////////////////////////
Uses
SysUtils, Math;
Type
TFloat64Helper = record helper for Float64
public
Function Round: Int64;
Procedure Add(const Value: Float64); inline;
Procedure Subtract(const Value: Float64); inline;
Procedure MultiplyBy(const Value: Float64); inline;
Function MultipliedBy(const Value: Float64): Float64; inline;
Procedure DivideBy(const Value: Float64); inline;
Function DividedBy(const Value: Float64): Float64; inline;
Function ToString: String; overload;
Function ToString(const Format: String): String; overload;
Function ToString(Decimals: Byte; SkipTrailingZeroDecimals: Boolean): string; overload;
Function ToString(Decimals: Byte; FixedDecimals,SkipTrailingZeroDecimals: Boolean): string; overload;
end;
////////////////////////////////////////////////////////////////////////////////
implementation
////////////////////////////////////////////////////////////////////////////////
Function TFloat64Helper.Round: Int64;
begin
Result := System.Round(Self);
end;
Procedure TFloat64Helper.Add(const Value: Float64);
begin
Self := Self + Value;
end;
Procedure TFloat64Helper.Subtract(const Value: Float64);
begin
Self := Self - Value;
end;
Procedure TFloat64Helper.MultiplyBy(const Value: Float64);
begin
Self := Value*Self;
end;
Function TFloat64Helper.MultipliedBy(const Value: Float64): Float64;
begin
Result := Value*Self;
end;
Procedure TFloat64Helper.DivideBy(const Value: Float64);
begin
Self := Self/Value;
end;
Function TFloat64Helper.DividedBy(const Value: Float64): Float64;
begin
Result := Self/Value;
end;
Function TFloat64Helper.ToString: String;
begin
Result := FloatToStr(Self);
end;
Function TFloat64Helper.ToString(const Format: String): String;
begin
Result := FormatFloat(Format,Self);
end;
Function TFloat64Helper.ToString(Decimals: Byte; SkipTrailingZeroDecimals: Boolean): string;
begin
if Decimals > 16 then Decimals := 16;
case Decimals of
// For performance use hard-coded format strings for low decimal values
0: Result := FormatFloat('0',Self);
1: if SkipTrailingZeroDecimals then
Result := FormatFloat('0.#',Self)
else
Result := FormatFloat('0.0',Self);
2: if SkipTrailingZeroDecimals then
Result := FormatFloat('0.##',Self)
else
Result := FormatFloat('0.00',Self);
3: if SkipTrailingZeroDecimals then
Result := FormatFloat('0.###',Self)
else
Result := FormatFloat('0.000',Self);
4: if SkipTrailingZeroDecimals then
Result := FormatFloat('0.####',Self)
else
Result := FormatFloat('0.0000',Self);
5: if SkipTrailingZeroDecimals then
Result := FormatFloat('0.#####',Self)
else
Result := FormatFloat('0.00000',Self);
else
// For higher values, use dynamic format string creation
if SkipTrailingZeroDecimals then
Result := FormatFloat('0.'+StringOfChar('#',Decimals),Self)
else
Result := FormatFloat('0.'+StringOfChar('0',Decimals),Self);
end;
end;
Function TFloat64Helper.ToString(Decimals: Byte; FixedDecimals,SkipTrailingZeroDecimals: Boolean): string;
// If not FixedDecimals the number of decimals decreases for big numbers, 1 less for each additional digit.
// Decimals gives the number of decimals when the absolute value is less than 1.
begin
if Decimals > 16 then Decimals := 16;
if FixedDecimals then Result := ToString(Decimals,SkipTrailingZeroDecimals) else
begin
var Threshold: UInt64 := 1;
var HideDecimals: Byte := 0;
while (Abs(Self) >= Threshold) and (HideDecimals < Decimals) do
begin
Inc(HideDecimals);
Threshold := 10*Threshold;
end;
Result := ToString(Decimals-HideDecimals,SkipTrailingZeroDecimals);
end;
end;
end.