Constructs Decimal from the floating point number using the Ryu algorithm.
Handle thousand separators for non exponential numbers.
Mir parsing supports up-to quadruple precision. The conversion error is 0 ULP for normal numbers. Subnormal numbers with an exponent greater than or equal to -512 have upper error bound equal to 1 ULP.
count of 64bit words in coefficient
import mir.test: should; import mir.conv: to; Decimal!128 decimal = void; DecimalExponentKey key; assert(decimal.fromStringImpl("3.141592653589793378e-10", key)); decimal.opCast!double.should == 0x1.596bf8ce7631ep-32; key.should == DecimalExponentKey.e;
import mir.conv: to; Decimal!3 decimal; DecimalExponentKey key; assert(decimal.fromStringImpl("0", key)); assert(key == DecimalExponentKey.none); assert(decimal.exponent == 0); assert(decimal.coefficient.length == 0); assert(!decimal.coefficient.sign); assert(cast(double) decimal.coefficient == 0); assert(decimal.fromStringImpl("-0.0", key)); assert(key == DecimalExponentKey.dot); assert(decimal.exponent == -1); assert(decimal.coefficient.length == 0); assert(decimal.coefficient.sign); assert(cast(double) decimal.coefficient == 0); assert(decimal.fromStringImpl("0e0", key)); assert(key == DecimalExponentKey.e); assert(decimal.exponent == 0); assert(decimal.coefficient.length == 0); assert(!decimal.coefficient.sign); assert(cast(double) decimal.coefficient == 0);
auto a = Decimal!1("777.7"); auto b = Decimal!1("777"); import mir.format; assert(stringBuf() << cast(double)a - cast(double)b << getData == "0.7000000000000455"); a -= b; assert(stringBuf() << a << getData == "0.7"); a = Decimal!1("-777.7"); b = Decimal!1("777"); a += b; assert(stringBuf() << a << getData == "-0.7"); a = Decimal!1("777.7"); b = Decimal!1("-777"); a += b; assert(stringBuf() << a << getData == "0.7"); a = Decimal!1("777"); b = Decimal!1("777.7"); a -= b; assert(stringBuf() << a << getData == "-0.7");
Check @nogc toString impl
import mir.format: stringBuf; auto str = "5.28238923728e-876543210"; auto decimal = Decimal!1(str); auto buffer = stringBuf; buffer << decimal; assert(buffer.data == str);
Decimal!4 i = "-0"; assert(i.view.coefficient.coefficients.length == 0); assert(i.coefficient.view.unsigned.coefficients.length == 0); assert(i.coefficient.view == 0L); assert(cast(long) i.coefficient == 0); assert(i.coefficient.sign);
auto str = "-3.4010447314490204552169750449563978034784726557588085989975288830070948234680e-13245"; auto decimal = Decimal!4(str); assert(decimal.toString == str, decimal.toString); decimal = Decimal!4.init; assert(decimal.toString == "0.0");
1 import mir.test: should; 2 3 import mir.conv: to; 4 Decimal!3 decimal; 5 DecimalExponentKey key; 6 7 // Check precise percentate parsing 8 assert(decimal.fromStringImpl("71.7", key, -2)); 9 key.should == DecimalExponentKey.dot; 10 // The result is exact value instead of 0.7170000000000001 = 71.7 / 100 11 (cast(double) decimal).should == 0.717; 12 13 assert(decimal.fromStringImpl("+0.334e-5"w, key)); 14 key.should == DecimalExponentKey.e; 15 (cast(double) decimal).should == 0.334e-5; 16 17 assert(decimal.fromStringImpl("100_000_000"w, key)); 18 key.should == DecimalExponentKey.none; 19 (cast(double) decimal).should == 1e8; 20 21 assert(decimal.fromStringImpl("-334D-5"d, key)); 22 key.should == DecimalExponentKey.D; 23 (cast(double) decimal).should == -334e-5; 24 25 assert(decimal.fromStringImpl("2482734692817364218734682973648217364981273648923423", key)); 26 key.should == DecimalExponentKey.none; 27 (cast(double) decimal).should == 2482734692817364218734682973648217364981273648923423.0; 28 29 assert(decimal.fromStringImpl(".023", key)); 30 key.should == DecimalExponentKey.dot; 31 (cast(double) decimal).should == .023; 32 33 assert(decimal.fromStringImpl("0E100", key)); 34 key.should == DecimalExponentKey.E; 35 (cast(double) decimal).should == 0; 36 37 foreach (str; ["-nan", "-NaN", "-NAN"]) 38 { 39 assert(decimal.fromStringImpl(str, key)); 40 assert(decimal.coefficient.length > 0); 41 assert(decimal.exponent == decimal.exponent.max); 42 assert(decimal.coefficient.sign); 43 key.should == DecimalExponentKey.nan; 44 auto nan = cast(double) decimal; 45 (cast(double) decimal).should == double.nan; 46 } 47 48 foreach (str; ["inf", "Inf", "INF"]) 49 { 50 assert(decimal.fromStringImpl(str, key)); 51 assert(decimal.coefficient.length == 0); 52 assert(decimal.exponent == decimal.exponent.max); 53 assert(key == DecimalExponentKey.infinity); 54 (cast(double) decimal).should == double.infinity; 55 } 56 57 assert(decimal.fromStringImpl("-inf", key)); 58 assert(decimal.coefficient.length == 0); 59 assert(decimal.exponent == decimal.exponent.max); 60 assert(key == DecimalExponentKey.infinity); 61 should(cast(double) decimal) == -double.infinity; 62 63 assert(!decimal.fromStringImpl("3.3.4", key)); 64 assert(!decimal.fromStringImpl("3.4.", key)); 65 assert(decimal.fromStringImpl("4.", key)); 66 assert(!decimal.fromStringImpl(".", key)); 67 assert(decimal.fromStringImpl("0.", key)); 68 assert(decimal.fromStringImpl("00", key)); 69 assert(!decimal.fromStringImpl("0d", key));
import mir.math.constant: PI; Decimal!2 decimal = "3.141592653589793378e-40"; // constructor assert(cast(double) decimal == double(PI) / 1e40);
// float and double can be used to construct Decimal of any length auto decimal64 = Decimal!1(-1.235e-7); assert(decimal64.exponent == -10); assert(decimal64.coefficient == -1235); // real number may need Decimal at least length of 2 auto decimal128 = Decimal!2(-1.235e-7L); assert(decimal128.exponent == -10); assert(decimal128.coefficient == -1235); decimal128 = Decimal!2(1234e3f); assert(decimal128.exponent == 3); assert(decimal128.coefficient == 1234);
Decimal!3 decimal; DecimalExponentKey key; assert(decimal.fromStringWithThousandsSeparatorImpl("12,345.678", ',', '.', key)); assert(cast(double) decimal == 12345.678); assert(key == DecimalExponentKey.dot); assert(decimal.fromStringWithThousandsSeparatorImpl("12,345,678", ',', '.', key, -3)); assert(cast(double) decimal == 12345.678); assert(key == DecimalExponentKey.none); assert(decimal.fromStringWithThousandsSeparatorImpl("021 345,678", ' ', ',', key)); assert(cast(double) decimal == 21345.678); assert(key == DecimalExponentKey.dot);
Stack-allocated decimal type.