www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Arbitrary precision decimal numbers

reply Ruby The Roobster <rubytheroobster yandex.com> writes:
Is there any implementation in phobos of something similar to 
BigInt but for non-integers as well?  If there isn't is there a 
dub package that does this, and if so, which one?
Aug 04 2022
next sibling parent reply frame <frame86 live.com> writes:
On Thursday, 4 August 2022 at 13:01:30 UTC, Ruby The Roobster 
wrote:
 Is there any implementation in phobos of something similar to 
 BigInt but for non-integers as well?  If there isn't is there a 
 dub package that does this, and if so, which one?
We have this: https://code.dlang.org/search?q=decimal I end up using BigInt instead on a custom wrapper that stores the precision hint. To calculate with any number, it need to convert each value to the same base (eg. storing 10.234 simply results in a BigInt with value 10234 and the precision hint of 3) and then forward the operation to BigInt.
Aug 05 2022
parent reply Ruby The Roobster <rubytheroobster yandex.com> writes:
On Friday, 5 August 2022 at 14:00:32 UTC, frame wrote:
 On Thursday, 4 August 2022 at 13:01:30 UTC, Ruby The Roobster 
 wrote:
 Is there any implementation in phobos of something similar to 
 BigInt but for non-integers as well?  If there isn't is there 
 a dub package that does this, and if so, which one?
We have this: https://code.dlang.org/search?q=decimal I end up using BigInt instead on a custom wrapper that stores the precision hint. To calculate with any number, it need to convert each value to the same base (eg. storing 10.234 simply results in a BigInt with value 10234 and the precision hint of 3) and then forward the operation to BigInt.
I'm already trying to make one, and I have a similar idea, but I ewant it extended to complex numbers. Also, what about division and exponentiation. You can't just forward them to BigInt and get a good result, BigInt will just round to an integer for these two.
Aug 05 2022
parent reply frame <frame86 live.com> writes:
On Friday, 5 August 2022 at 14:03:36 UTC, Ruby The Roobster wrote:

 Also, what about division and exponentiation.  You can't just 
 forward them to BigInt and get a good result, BigInt will just 
 round to an integer for these two.
There are divMod() and powmod() for BigInt but I have no idea how precise they really are.
Aug 05 2022
parent reply Ruby The Roobster <rubytheroobster yandex.com> writes:
On Friday, 5 August 2022 at 14:11:10 UTC, frame wrote:
 On Friday, 5 August 2022 at 14:03:36 UTC, Ruby The Roobster 
 wrote:

 Also, what about division and exponentiation.  You can't just 
 forward them to BigInt and get a good result, BigInt will just 
 round to an integer for these two.
There are divMod() and powmod() for BigInt but I have no idea how precise they really are.
I'm currently working on an arbitrarily precise division algortihm based off of the done-by-hand standard algorithm, but I need to get it to work for complex numbers, [which it's just not](https://forum.dlang.org/post/czidpbdywsohstyviitk forum.dlang.org).
Aug 05 2022
parent reply Dom Disc <dominikus scherkl.de> writes:
On Friday, 5 August 2022 at 14:25:39 UTC, Ruby The Roobster wrote:
 I'm currently working on an arbitrarily precise division 
 algortihm based off of the done-by-hand standard algorithm, but 
 I need to get it to work for complex numbers, [which it's just 
 not](https://forum.dlang.org/post/czidpbdywsohstyviitk forum.dlang.org).
I once did a completely inline implementation of xlcmplx based on an arbitrary precision float (in this context called xlfloat) in C++. You only need to exchange xlfloat with your floatingpoint type: ```C class xlcmplx { xlfloat Re, Im; public: friend inline void swap(xlcmplx& a, xlcmplx& b) { swap(a.Re, b.Re); swap(a.Im, b.Im); } xlcmplx(const xlfloat& re =0, const xlfloat& im =0) : Re(re), Im(im) { } xlcmplx(const xlcmplx& c) : Re(c.Re), Im(c.Im) { } // two special "constructors": friend inline xlcmplx i(const xlfloat& x =1) { return xlcmplx(0,x); } // make pure imaginary number friend inline xlcmplx polar(const xlfloat& arg, const xlfloat& norm =1) { return (!norm || !arg) ? norm : xlcmplx(cos(arg),sin(arg)) *= norm; } uint32 Decimal(char* s, uint32 max) const; // string representation inline xlcmplx& operator=(const xlcmplx& c) { if(this != &c) Re = c.Re, Im = c.Im; return *this; } inline xlcmplx& operator=(const xlfloat& f) { Re = f, Im = 0; return *this; } inline xlcmplx& operator+() { return *this; } // dummy operator inline xlcmplx operator-() const { return xlcmplx(-Re, -Im); } inline xlcmplx& operator+=(const xlcmplx& c) { Re += c.Re; Im += c.Im; return *this; } inline xlcmplx& operator+=(const xlfloat& f) { Re += f; return *this; } inline xlcmplx& operator-=(const xlcmplx& c) { Re -= c.Re; Im -= c.Im; return *this; } inline xlcmplx& operator-=(const xlfloat& f) { Re -= f; return *this; } inline xlcmplx& operator*=(const xlcmplx& c) { xlfloat t = Re; t *= c.Re; t -= Im*c.Im; Im *= c.Re; Im += Re*c.Im; Re = t; return *this; } inline xlcmplx& operator*=(const xlfloat& f) { Re *= f; Im *= f; return *this; } inline xlcmplx& operator/=(const xlcmplx& c) { return *this *= inv(c); } inline xlcmplx& operator/=(const xlfloat& f) { Re /= f; Im /= f; return *this; } inline bool operator==(const xlcmplx& c) const { return Im == c.Im && Re == c.Re; } inline bool operator==(const xlfloat& f) const { return !Im && Re == f; } inline bool operator!=(const xlcmplx& c) const { return Im != c.Im || Re != c.Re; } inline bool operator!=(const xlfloat& f) const { return !!Im || Re != f; } friend inline const xlfloat& real(const xlcmplx& c) { return c.Re; } friend inline const xlfloat& imag(const xlcmplx& c) { return c.Im; } friend inline xlfloat norm(const xlcmplx& c) { return c.Im ? c.Re ? sqr(quad(c.Re)+quad(c.Im)) : abs(c.Im) : abs(c.Re); } friend inline xlfloat arg(const xlcmplx& c) { return atan2(c.Re, c.Im); } // an angle in [0..2*pi[ friend inline xlcmplx conj(xlcmplx c) { c.Im.neg(); return c; } friend inline xlcmplx inv(const xlcmplx& c) { xlfloat t = quad(c.Re); t += quad(c.Im); return conj(c) /= t; } friend inline xlcmplx quad(const xlcmplx& c) { return xlcmplx(quad(c.Re)-quad(c.Im),(c.Re*c.Im)<<1); } friend inline xlcmplx exp(const xlcmplx& c) { return c.Im ? xlcmplx(cos(c.Im), sin(c.Im)) *= exp(c.Re) : exp(c.Re); } friend inline xlcmplx sin(const xlcmplx& c) { return c.Im ? c.Re ? xlcmplx(sin(c.Re)*cosh(c.Im), cos(c.Re)*sinh(c.Im)) : i(sinh(c.Im)) : sin(c.Re); } friend inline xlcmplx cos(const xlcmplx& c) { return c.Im ? c.Re ? xlcmplx(cos(c.Re)*cosh(c.Im), sin(c.Re)*sinh(c.Im)) : cosh(c.Im) : cos(c.Re); } friend inline xlcmplx ln(const xlcmplx& c) { return xlcmplx(ln(norm(c)), arg(c)); } // main value - multiples of 2*pi*i added are also valid results }; inline bool operator==(const xlfloat& f, const xlcmplx& c) { return c == f; } inline bool operator!=(const xlfloat& f, const xlcmplx& c) { return c != f; } inline xlcmplx operator+(xlcmplx a, const xlcmplx& b) { return a += b; } inline xlcmplx operator+(xlcmplx a, const xlfloat& b) { return a += b; } inline xlcmplx operator+(const xlfloat& a, xlcmplx b) { return b += a; } inline xlcmplx operator-(xlcmplx a, const xlcmplx& b) { return a -= b; } inline xlcmplx operator-(xlcmplx a, const xlfloat& b) { return a -= b; } inline xlcmplx operator-(const xlfloat& a, const xlcmplx& b) { return -b += a; } inline xlcmplx operator*(xlcmplx a, const xlfloat& b) { return a *= b; } inline xlcmplx operator*(xlcmplx a, const xlcmplx& b) { return a *= b; } inline xlcmplx operator*(const xlfloat& a, xlcmplx b) { return b *= a; } inline xlcmplx operator/(xlcmplx a, const xlcmplx& b) { return a /= b; } inline xlcmplx operator/(xlcmplx a, const xlfloat& b) { return a /= b; } inline xlcmplx operator/(const xlfloat& a, const xlcmplx& b) { return xlcmplx(a) /= b; } inline xlcmplx pow(const xlcmplx& c, const int exp) { return polar(arg(c)*exp, pow(norm(c), exp)); } inline xlcmplx pow(const xlcmplx& c, const xlfloat& exp) { return polar(arg(c)*exp, pow(norm(c), exp)); } inline xlcmplx log(const xlcmplx& c, const uint32 base = 10) { return ln(c) /= ln(number(base)); } ``` You can also get the implementation of xlfloat, if you like - but that one is NOT completely inline and much longer :-D
Aug 06 2022
parent Dom Disc <dominikus scherkl.de> writes:
On Saturday, 6 August 2022 at 11:25:28 UTC, Dom Disc wrote:
 I once did a completely inline implementation of xlcmplx
Sorry, one function is NOT inline:
 ```C
 class xlcmplx
 {
 	uint32 Decimal(char* s, uint32 max) const; // string 
 representation
 }
 ```
But you should forget about that, because D has much better methods to create a string. In fact good enough that also this function could have been inline... but in D the whole concept of headers is superfluous, so who cares.
Aug 06 2022
prev sibling parent reply Sergey <kornburn yandex.ru> writes:
On Thursday, 4 August 2022 at 13:01:30 UTC, Ruby The Roobster 
wrote:
 Is there any implementation in phobos of something similar to 
 BigInt but for non-integers as well?  If there isn't is there a 
 dub package that does this, and if so, which one?
Also you could find usefull such projects: http://mir-algorithm.libmir.org/mir_bignum_decimal.html https://github.com/huntlabs/hunt-extra/blob/2d286f939193fc0cd55c799906f7657cec502dc8/source/hunt/math/BigDecimal.d
Aug 06 2022
parent reply Ruby The Roobster <rubytheroobster yandex.com> writes:
On Saturday, 6 August 2022 at 13:20:19 UTC, Sergey wrote:
 On Thursday, 4 August 2022 at 13:01:30 UTC, Ruby The Roobster 
 wrote:
 Is there any implementation in phobos of something similar to 
 BigInt but for non-integers as well?  If there isn't is there 
 a dub package that does this, and if so, which one?
Also you could find usefull such projects: http://mir-algorithm.libmir.org/mir_bignum_decimal.html https://github.com/huntlabs/hunt-extra/blob/2d286f939193fc0cd55c799906f7657cec502dc8/source/hunt/math/BigDecimal.d
It doesn't provide for arithmetic operations though, according to the docs.
Aug 10 2022
parent Tejas <notrealemail gmail.com> writes:
On Wednesday, 10 August 2022 at 14:11:04 UTC, Ruby The Roobster 
wrote:
 On Saturday, 6 August 2022 at 13:20:19 UTC, Sergey wrote:
 On Thursday, 4 August 2022 at 13:01:30 UTC, Ruby The Roobster 
 wrote:
 Is there any implementation in phobos of something similar to 
 BigInt but for non-integers as well?  If there isn't is there 
 a dub package that does this, and if so, which one?
Also you could find usefull such projects: http://mir-algorithm.libmir.org/mir_bignum_decimal.html https://github.com/huntlabs/hunt-extra/blob/2d286f939193fc0cd55c799906f7657cec502dc8/source/hunt/math/BigDecimal.d
It doesn't provide for arithmetic operations though, according to the docs.
Maybe you'll have better luck with this? https://code.dlang.org/packages/gmp-d
Aug 10 2022