Another take on decimal data types

kdevel kdevel at vogtner.de
Sat Jan 13 18:37:10 UTC 2018


On Saturday, 13 January 2018 at 17:46:15 UTC, rumbu wrote:
> The following code works:
>
>     real r;
>     for (r = 1; r < 6; r += .1L) {
>         decimal128 d = r;
>         auto dsin = sin (d);
>         auto rsin = sin (r);
>         auto delta = dsin - rsin; //delta is decimal128
>         writefln ("%9.2f %30.24f %30.24f %12.4g", r, rsin, 
> dsin, delta);
>     }

rsinus.d
```
import std.stdio;
import std.math;
import decimal;

void main ()
{
    real r;
    for (r = 1; r < 6; r += .1L) {
       decimal128 d = r;
       auto dsin = sin (d);
       auto rsin = sin (r);
       auto delta = dsin - rsin;
       writefln ("%9.2f %30.24f %30.24f %12.4g", r, rsin, dsin, 
delta);
    }
}
```

I get large numerical dicrepancies and an exception:

      1.00     0.841470984807896506664591     
0.841470984807896506632968    3.633e-18
      1.10     0.891207360061435339970703     
0.878166666666666700439167       -1e-02
      1.20     0.932039085967226349689098     
0.932735999999999982229600        1e-04
      1.30     0.963558185417192964729825     
0.964774416666666678037840        1e-03
      1.40     0.985449729988460180693261     
0.985449729988460165022208    2.352e-17
      1.50     0.997494986604054430972058     
0.997494986604054430940101   -1.206e-17
      1.60     0.999573603041505164359688     
0.917333333333333309393333       -1e-02
      1.70     0.991664810452468615338453     
0.991664810452468621659666    5.316e-17
      1.80     0.973847630878195186514452     
0.973847630878195177217801    3.222e-17
      1.90     0.946300087687414488452770     
0.946300087687414518558711    5.006e-17
      2.00     0.909297426825681695322298     
0.909297426825681695408286   -1.229e-17
      2.10     0.863209366648873770600393     
0.863209366648873727768592   -9.243e-17
      2.20     0.808496403819590184279108     
0.808496403819590083669388   -1.180e-16
      2.30     0.745705212176720177432929     
0.745705212176720299976718    1.573e-16
      2.40     0.675463180551150926659871     
0.675463180551150998081025    4.488e-17
      2.50     0.598472144103956494242628     
0.598472144103956494052117   -5.365e-17
      2.60     0.515501371821464235509908     
0.515501371821464164136844   -1.059e-16
      2.70     0.427379880233829934906920     
0.427379880233829779962563   -1.640e-16
      2.80     0.334988150155904919986691     
0.334988150155905092912699    1.534e-16
      2.90     0.239249329213982328722001     
0.239249329213982423337949    8.154e-17
      3.00     0.141120008059867222739193     
0.141120008059867222100109    9.000e-18
      3.10     0.041580662433290579926783     
0.041580662433290496264607   -8.502e-17
      3.20    -0.058374143427579908318645    
-0.058374143427580079845578   -1.746e-16
      3.30    -0.157745694143248381115198    
-0.157745694143248199327762    1.774e-16
      3.40    -0.255541102026831318288136    
-0.255541102026831224503296    1.098e-16
      3.50    -0.350783227689619847116916    
-0.350783227689619848119312   -1.252e-17
      3.60    -0.442520443294852383234834    
-0.442520443294852457798085   -5.310e-17
      3.70    -0.529836140908493212172466    
-0.529836140908493358228498   -1.787e-16
      3.80    -0.611857890942719074699619    
-0.611857890942718929385788    9.811e-17
      3.90    -0.687766159183973817053612    
-0.687766159183973746224122    2.078e-17
      4.00    -0.756802495307928250372134    
-0.756802495307928251373997   -5.067e-17
      4.10    -0.818277111064410503490831    
-0.818277111064410297331800    1.797e-16
      4.20    -0.871575772413588059281658    
-0.871575772413588143861425   -6.686e-17
      4.30    -0.916165936749454983402223    
-0.916165936749454908701153    1.013e-16
      4.40    -0.951602073889515953533484    
-0.951602073889516059449964   -1.634e-16
      4.50    -0.977530117665097055001684    
-0.977530117665097055387688   -4.889e-17
      4.60    -0.993691003633464455912887    
-0.993691003633464414974720   -8.475e-18
      4.70    -0.999923257564100884174467    
-0.999923257564100886240565   -5.624e-17
      4.80    -0.996164608835840671935500    
-0.996164608835840688651004   -8.651e-18
      4.90    -0.982452612624332512691275    
-0.982452612624332448489733    2.651e-17
      5.00    -0.958924274663138469525139    
-0.958924274663138468894495   -1.739e-17
      5.10    -0.925814682327732297803524    
-0.925814682327732436044974   -9.704e-17
      5.20    -0.883454655720153265790421    
-0.883454655720153186437488    5.926e-17
      5.30    -0.832267442223901164892897    
-0.832267442223901270573400   -1.281e-16
      5.40    -0.772764487555987363974919    
-0.772764487555987145324893    2.202e-16
      5.50    -0.705540325570391908089566    
-0.705540325570391906230803    1.647e-17
      5.60    -0.631266637872321313522395    
-0.631266637872321596869491   -3.079e-16
      5.70    -0.550685542597637763537807   
-25.165500000000002545915000          -

core.exception.RangeError at decimal/package.d(6652): Range violation
----------------
??:? _d_arrayboundsp [0x46ccea]
decimal/package.d:6652 void decimal.sinkFloat!(char, 
decimal.integrals.unsigned!(128).unsigned).sinkFloat(ref 
const(std.format.FormatSpec!(char).FormatSpec), void 
delegate(const(char)[]), 
const(decimal.integrals.unsigned!(128).unsigned), const(int), 
const(bool), const(decimal.RoundingMode), const(bool)) [0x460a41]
decimal/package.d:6851 void decimal.sinkGeneral!(char, 
decimal.integrals.unsigned!(128).unsigned).sinkGeneral(ref 
const(std.format.FormatSpec!(char).FormatSpec), void 
delegate(const(char)[]), 
const(decimal.integrals.unsigned!(128).unsigned), const(int), 
const(bool), const(decimal.RoundingMode)) [0x461ae9]
decimal/package.d:6890 void decimal.sinkDecimal!(char, 
decimal.Decimal!(128).Decimal).sinkDecimal(ref 
const(std.format.FormatSpec!(char).FormatSpec), void 
delegate(const(char)[]), ref 
const(decimal.Decimal!(128).Decimal), 
const(decimal.RoundingMode)) [0x460208]
decimal/package.d:1316 const void 
decimal.Decimal!(128).Decimal.toString!(char).toString(scope void 
delegate(const(char)[]), std.format.FormatSpec!(char).FormatSpec) 
[0x45fff1]
/.../dmd2/linux/bin64/../../src/phobos/std/format.d:3341 void 
std.format.formatObject!(std.stdio.File.LockingTextWriter, 
decimal.Decimal!(128).Decimal, char).formatObject(ref 
std.stdio.File.LockingTextWriter, ref 
decimal.Decimal!(128).Decimal, ref 
const(std.format.FormatSpec!(char).FormatSpec)) [0x4620c2]
/.../dmd2/linux/bin64/../../src/phobos/std/format.d:3669 void 
std.format.formatValue!(std.stdio.File.LockingTextWriter, 
decimal.Decimal!(128).Decimal, char).formatValue(ref 
std.stdio.File.LockingTextWriter, ref 
decimal.Decimal!(128).Decimal, ref 
const(std.format.FormatSpec!(char).FormatSpec)) [0x462069]
/.../dmd2/linux/bin64/../../src/phobos/std/format.d:568 uint 
std.format.formattedWrite!(std.stdio.File.LockingTextWriter, 
char, real, real, decimal.Decimal!(128).Decimal, 
decimal.Decimal!(128).Decimal).formattedWrite(ref 
std.stdio.File.LockingTextWriter, const(char[]), real, real, 
decimal.Decimal!(128).Decimal, decimal.Decimal!(128).Decimal) 
[0x45711b]
/.../dmd2/linux/bin64/../../src/phobos/std/stdio.d:1496 void 
std.stdio.File.writefln!(char, real, real, 
decimal.Decimal!(128).Decimal, 
decimal.Decimal!(128).Decimal).writefln(const(char[]), real, 
real, decimal.Decimal!(128).Decimal, 
decimal.Decimal!(128).Decimal) [0x456be6]
/.../dmd2/linux/bin64/../../src/phobos/std/stdio.d:3797 void 
std.stdio.writefln!(char, real, real, 
decimal.Decimal!(128).Decimal, 
decimal.Decimal!(128).Decimal).writefln(const(char[]), real, 
real, decimal.Decimal!(128).Decimal, 
decimal.Decimal!(128).Decimal) [0x456b37]
rsinus.d:12 _Dmain [0x44c27d]

> if you really need to convert decimalX values to floating point 
> counterparts, you'll need to cast them:
>
> x = cast(real)somedecimalvalue;
>
> (but update your files before this, I discovered a bug in 
> opCast)

Yea, this seems to work now.


More information about the Digitalmars-d-announce mailing list