January 01, 2020
On Wednesday, 1 January 2020 at 22:04:00 UTC, IGotD- wrote:
> Using floating point is not recommended. For some fractional number it is actually impossible to store the value as a rational binary number. For example 8.90 would be stored as 8.89999999999+ (in reality this is binary values so just think of my example in an equivalent binary value case). This would lead to some rounding errors, especially when chaining several operations.

No, not if you store as cents. You get the exact same values as with 53 bits integers with IEEE754.

You have to pay atttentition to rounding mode, even-odd is common.


> You should go for a representation that always calculates the currency exact, down to the cent or whatever it is. Not doing so you might even be breaking the law for some appliances.

Double will do that fine. As I said, same as integer.  If you need half-cents, just multiply with 200 instead of 100. Or you could use millis (multiply by 1000).


January 02, 2020
On Wednesday, 1 January 2020 at 15:41:32 UTC, Vitaly Livshic wrote:
> Good day.
>
> I came from Java world, where 'double' type inadequate for money calculation. BigDecimal serves for it. This is ugly type, but gives precise results.
>
> Which type I must use for money in D?

You can use this package:

https://code.dlang.org/packages/money
January 02, 2020
On Wednesday, 1 January 2020 at 22:26:30 UTC, Ola Fosheim Grøstad wrote:
> On Wednesday, 1 January 2020 at 22:04:00 UTC, IGotD- wrote:
>> Using floating point is not recommended. For some fractional number it is actually impossible to store the value as a rational binary number. For example 8.90 would be stored as 8.89999999999+ (in reality this is binary values so just think of my example in an equivalent binary value case). This would lead to some rounding errors, especially when chaining several operations.
>
> No, not if you store as cents. You get the exact same values as with 53 bits integers with IEEE754.
>
> You have to pay atttentition to rounding mode, even-odd is common.
>
>
>> You should go for a representation that always calculates the currency exact, down to the cent or whatever it is. Not doing so you might even be breaking the law for some appliances.
>
> Double will do that fine. As I said, same as integer.  If you need half-cents, just multiply with 200 instead of 100. Or you could use millis (multiply by 1000).

Yyou're all silly guys. Don't use floating point for currency, just make a Currency fixed point custom type.
January 02, 2020
On Thursday, 2 January 2020 at 13:58:17 UTC, Basile B. wrote:
> Yyou're all silly guys. Don't use floating point for currency, just make a Currency fixed point custom type.

Drop the adhominem.

If you understand the floating point hardware specification then there are no issues with floating point.


January 02, 2020
On Thu, 2020-01-02 at 14:34 +0000, Ola Fosheim Grøstad via Digitalmars- d wrote:
> 
[…]
> If you understand the floating point hardware specification then there are no issues with floating point.
> 

I am not an expert in this, but I have seen lots of rants and arguments on this over the years.

As I understand it the core problem is needing base 10 numbers not base 2 ones – converting between them causes problems – and using hardware floating point does not have enough accuracy for compliance with requirements of FCA for financial calculations.

There are various people on the ACCU general mailing list and the LJC emailing list who know much more about this than I do as they work on these things on a daily basis. I could ask there for pointers as to why money types are such an obsession.

-- 
Russel.
===========================================
Dr Russel Winder      t: +44 20 7585 2200
41 Buckmaster Road    m: +44 7770 465 077
London SW11 1EN, UK   w: www.russel.org.uk



January 02, 2020
On Thursday, 2 January 2020 at 17:18:04 UTC, Russel Winder wrote:
> On Thu, 2020-01-02 at 14:34 +0000, Ola Fosheim Grøstad via Digitalmars- d wrote:
>> 
> […]
>> If you understand the floating point hardware specification then there are no issues with floating point.
>> 
>
> I am not an expert in this, but I have seen lots of rants and arguments on this over the years.
>
> As I understand it the core problem is needing base 10 numbers not base 2 ones – converting between them causes problems – and using hardware floating point does not have enough accuracy for compliance with requirements of FCA for financial calculations.

Oh, I am not arguing that banking institutions should use base 2 floating point. 64 bit floating point base 2 can only represent 90 trillion cents with exact precision, so if they do calculations involving base 10 constants that could easily lead to problems... (And jurisdictions have various rules for how to deal with the sub-cent remainder I believe).

But you have the same issues with bit-limited base-2 fixed point, and it is easy to make mistakes with fixed bit fix point in non-trivial formulas!

So, if correctness is important then you could use decimal (the exact Pythonic numeric type), large base-10 floats (rare in hardware), or big-int rationals (in this case base2 is ok, you take care of the remainder at the end)...

Power9 from IBM apparently has 128 bits floating point, and IIRC some IBM machines have base 10 floating point hardware, but that is rather esoteric...

In the more mundane world of every-day-computing you have to be able to represent currency in web clients and in TypeScript/JavaScript 64bit IEEE754 is the only reasonable alternative.

So if you want the same representation on the server and the client then it can be useful to use 64bit floating point. Although, it is sometimes useful to store them ints as Steve suggested.



January 02, 2020
On Thursday, 2 January 2020 at 17:57:19 UTC, Ola Fosheim Grøstad wrote:
> Oh, I am not arguing that banking institutions should use base 2 floating point. 64 bit floating point base 2 can only represent 90 trillion cents with exact precision,

Typo: 90 trillion USD, so 9000 trillion cents.

I.e. the range is -2^53 to 2^53, so basically a 54 bit signed integer with exact representation.


January 02, 2020
On Thu, Jan 02, 2020 at 05:18:04PM +0000, Russel Winder via Digitalmars-d wrote: [...]
> As I understand it the core problem is needing base 10 numbers not base 2 ones – converting between them causes problems – and using hardware floating point does not have enough accuracy for compliance with requirements of FCA for financial calculations.

AFAIK, the crux of the problem with using binary floating point types for money representation is that the former's base-2 rounding behaviour does not 100% match the latter's expected base-10 rounding behaviour. This discrepancy is a big problem because in financial applications 100% identical behaviour with base-10 rounding is a non-negotiable requirement.


T

-- 
Having a smoking section in a restaurant is like having a peeing section in a swimming pool. -- Edward Burr
January 02, 2020
On Thursday, 2 January 2020 at 17:59:40 UTC, H. S. Teoh wrote:
> AFAIK, the crux of the problem with using binary floating point types for money representation is that the former's base-2 rounding behaviour does not 100% match the latter's expected base-10 rounding behaviour. This discrepancy is a big problem because in financial applications 100% identical behaviour with base-10 rounding is a non-negotiable requirement.

You can set the rounding mode. Round to even is the common default I believe (bankers rounding). Although I think it is common to just round up at 0.5 when doing manual accounting.

So you can get the same behaviour when storing in cents, but you then need to do the downscaling as the last step. So you need to take care to get correct results.

E.g. to get 3% of 123 cents: (3*123.0)/100

Although 25% is no problem: 0.25*123.0  (since 0.25 has an exact representation in base 2 floating point)

So it is easy to make mistakes. Same argument for fixed point.

With base 10 representation that is no longer a problem.
Same with base 2 rational, as you do the rounding in the last step.

January 02, 2020
On Thursday, 2 January 2020 at 18:20:38 UTC, Ola Fosheim Grøstad wrote:
> E.g. to get 3% of 123 cents: (3*123.0)/100

Whoops, too quick, that won't work.

You need to set the rounding mode first and then do the truncating.  E.g. you can do the same calculation twice with round up/round down and do basic rounding. If you get the same result, then it is right. But easy to make mistakes... like I just demonstrated.. :-P