Skip to content

Commit 8858e10

Browse files
committed
add percentage parsing
1 parent e51ce35 commit 8858e10

File tree

2 files changed

+31
-14
lines changed

2 files changed

+31
-14
lines changed

source/mir/bignum/decimal.d

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ struct Decimal(size_t maxSize64)
4646
}
4747

4848
///
49-
this(C)(scope const(C)[] str) @safe pure @nogc
49+
this(C)(scope const(C)[] str, int exponentShift = 0) @safe pure @nogc
5050
if (isSomeChar!C)
5151
{
5252
DecimalExponentKey key;
53-
if (fromStringImpl(str, key) || key == DecimalExponentKey.nan || key == DecimalExponentKey.infinity)
53+
if (fromStringImpl(str, key, exponentShift) || key == DecimalExponentKey.nan || key == DecimalExponentKey.infinity)
5454
return;
5555
static if (__traits(compiles, () @nogc { throw new Exception("Can't parse Decimal."); }))
5656
{
@@ -119,7 +119,16 @@ struct Decimal(size_t maxSize64)
119119
Returns: false in case of overflow or incorrect string.
120120
Precondition: non-empty coefficients.
121121
+/
122-
bool fromStringImpl(C, bool allowSpecialValues = true, bool allowDotOnBounds = true, bool allowDExponent = true, bool allowStartingPlus = true, bool checkEmpty = true, bool allowUnderscores = true, bool allowLeadingZeros = true)(scope const(C)[] str, out DecimalExponentKey key)
122+
bool fromStringImpl(C,
123+
bool allowSpecialValues = true,
124+
bool allowDotOnBounds = true,
125+
bool allowDExponent = true,
126+
bool allowStartingPlus = true,
127+
bool allowUnderscores = true,
128+
bool allowLeadingZeros = true,
129+
bool checkEmpty = true,
130+
)
131+
(scope const(C)[] str, out DecimalExponentKey key, int exponentShift = 0)
123132
@safe pure @nogc nothrow
124133
if (isSomeChar!C)
125134
{
@@ -161,7 +170,6 @@ struct Decimal(size_t maxSize64)
161170
exponent = 0;
162171

163172
ulong v;
164-
uint afterDot;
165173
bool dot;
166174
static if (allowUnderscores)
167175
{
@@ -225,11 +233,11 @@ struct Decimal(size_t maxSize64)
225233
}
226234
S:
227235
v += d;
228-
afterDot += dot;
236+
exponentShift -= dot;
229237
if (str.length)
230238
continue;
231239
E:
232-
exponent -= afterDot;
240+
exponent += exponentShift;
233241
R:
234242
coefficient.data[0] = v;
235243
coefficient.length = v != 0;
@@ -321,7 +329,7 @@ struct Decimal(size_t maxSize64)
321329
{
322330
import mir.bignum.low_level_view: DecimalView, BigUIntView, MaxWordPow10;
323331
auto work = DecimalView!size_t(false, 0, BigUIntView!size_t(coefficient.data));
324-
auto ret = work.fromStringImpl!(C, allowSpecialValues, allowDExponent, allowStartingPlus, checkEmpty, allowUnderscores, allowLeadingZeros)(str, key);
332+
auto ret = work.fromStringImpl!(C, allowSpecialValues, allowDExponent, allowStartingPlus, allowUnderscores, allowLeadingZeros, checkEmpty)(str, key, exponentShift);
325333
coefficient.length = cast(uint) work.coefficient.coefficients.length;
326334
coefficient.sign = work.sign;
327335
exponent = work.exponent;
@@ -339,9 +347,11 @@ struct Decimal(size_t maxSize64)
339347
Decimal!3 decimal;
340348
DecimalExponentKey key;
341349

342-
assert(decimal.fromStringImpl("1.334", key));
350+
// Check precise percentate parsing
351+
assert(decimal.fromStringImpl("71.7", key, -2));
343352
assert(key == DecimalExponentKey.dot);
344-
assert(cast(double) decimal == 1.334);
353+
// The result is exact value instead of 0.7170000000000001 = 71.7 / 100
354+
assert(cast(double) decimal == 0.717);
345355

346356
assert(decimal.fromStringImpl("+0.334e-5"w, key));
347357
assert(key == DecimalExponentKey.e);

source/mir/bignum/low_level_view.d

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,9 +2046,17 @@ struct DecimalView(W, WordEndian endian = TargetEndian, Exp = sizediff_t)
20462046
/++
20472047
Returns: false in case of overflow or incorrect string.
20482048
Precondition: non-empty coefficients
2049-
Note: doesn't support signs.
20502049
+/
2051-
bool fromStringImpl(C, bool allowSpecialValues = true, bool allowDotOnBounds = true, bool allowDExponent = true, bool allowStartingPlus = true, bool checkEmpty = true, bool allowUnderscores = true, bool allowLeadingZeros = true)(scope const(C)[] str, out DecimalExponentKey key)
2050+
bool fromStringImpl(C,
2051+
bool allowSpecialValues = true,
2052+
bool allowDotOnBounds = true,
2053+
bool allowDExponent = true,
2054+
bool allowStartingPlus = true,
2055+
bool allowUnderscores = true,
2056+
bool allowLeadingZeros = true,
2057+
bool checkEmpty = true,
2058+
)
2059+
(scope const(C)[] str, out DecimalExponentKey key, int exponentShift = 0)
20522060
@safe pure @nogc nothrow
20532061
if (isSomeChar!C)
20542062
{
@@ -2094,7 +2102,6 @@ struct DecimalView(W, WordEndian endian = TargetEndian, Exp = sizediff_t)
20942102

20952103
W v;
20962104
W t = 1;
2097-
uint afterDot;
20982105
bool dot;
20992106

21002107
static if (allowUnderscores)
@@ -2159,7 +2166,7 @@ struct DecimalView(W, WordEndian endian = TargetEndian, Exp = sizediff_t)
21592166
S:
21602167
t *= 10;
21612168
v += d;
2162-
afterDot += dot;
2169+
exponentShift -= dot;
21632170

21642171
if (_expect(t == mp10 || str.length == 0, false))
21652172
{
@@ -2182,7 +2189,7 @@ struct DecimalView(W, WordEndian endian = TargetEndian, Exp = sizediff_t)
21822189
if (str.length == 0)
21832190
{
21842191
M:
2185-
exponent -= afterDot;
2192+
exponent += exponentShift;
21862193
coefficient = work.mostSignificant == 0 ? coefficient.init : work;
21872194
static if (allowUnderscores)
21882195
{

0 commit comments

Comments
 (0)