Re: Is using floating point type for money/currency a good idea?

2020-08-20 Thread Steven Lee via Digitalmars-d-learn
Me and my financial adviser think not. Unfortunately, this is not 
the best way..


Re: Is using floating point type for money/currency a good idea?

2019-05-20 Thread rikki cattermole via Digitalmars-d-learn

On 20/05/2019 11:10 PM, Boqsc wrote:

https://dlang.org/spec/float.html

I'm frozen in learning basics of D lang since I want to create a simple 
game and I really would like a clean and simple code, however to me 
floating points are magic.


https://wiki.dlang.org/Review_Queue
Since std.decimal is still work in progress and apparently its 
development is stuck for a while, should I just somehow use floating 
point to store currency or wait until Decimal package will be finally 
included into std Phobos of D lang?


While other posters have explained the best practice for currency in the 
real world, for games even AAA uses floats. Don't fret it, it doesn't 
matter. You won't loose actual money if its off by a few cents here or 
there.


Re: Is using floating point type for money/currency a good idea?

2019-05-20 Thread H. S. Teoh via Digitalmars-d-learn
On Mon, May 20, 2019 at 11:10:32AM +, Boqsc via Digitalmars-d-learn wrote:
> https://dlang.org/spec/float.html
> 
> I'm frozen in learning basics of D lang since I want to create a
> simple game and I really would like a clean and simple code, however
> to me floating points are magic.

Read this:

https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html


> https://wiki.dlang.org/Review_Queue
> Since std.decimal is still work in progress and apparently its
> development is stuck for a while, should I just somehow use floating
> point to store currency or wait until Decimal package will be finally
> included into std Phobos of D lang?

You do *not* want to use floating-point for money/currency (unless your
currency is in base 2). This is because certain decimal fractions cannot
be represented exactly in binary, and sooner or later you will run into
unexpected roundoff errors.

Just use a plain old integer with a fixed decimal point. I.e., 10.25 is
represented as 1025 with an implicit division by 100.  I wouldn't even
bother with BigInt unless you expect to be dealing with sub-cent money
amounts or extremely large amounts of money. BigInt allows arbitrary
precision, but at the cost of slower operations. For a game, it's
overkill. Just use int (or long) with fixed-point operations.


T

-- 
PNP = Plug 'N' Pray


Re: Is using floating point type for money/currency a good idea?

2019-05-20 Thread kdevel via Digitalmars-d-learn

On Monday, 20 May 2019 at 11:47:25 UTC, Josh wrote:

On Monday, 20 May 2019 at 11:10:32 UTC, Boqsc wrote:

https://dlang.org/spec/float.html

I'm frozen in learning basics of D lang since I want to create 
a simple game and I really would like a clean and simple code, 
however to me floating points are magic.


https://wiki.dlang.org/Review_Queue
Since std.decimal is still work in progress and apparently its 
development is stuck for a while, should I just somehow use 
floating point to store currency or wait until Decimal package 
will be finally included into std Phobos of D lang?


Normally I would say no, no and no.  Rounding issues will kill 
you every time.


Right. Say a chemical is sold at 3165 $/m³. A customer orders
1 ℓ. According to the "round to nearest or even" rule what is the 
amount

invoiced (no taxes)? For the non-SI world: 1 m³ = 1000 ℓ.

[...]

writefln("%f", cast(float) i / 100.0);

[...]

Why cast the integer to float and then device by a double?

   writefln("%f", i / 100.);

accomplishes the same with less reading.

Back to the invoice: I would like to promote decimal here:

import std.stdio;
import std.math;
import std.conv;
import decimal;

void calculate (T) ()
{
   writefln ("\n%s", T.stringof);
   T price_per_m3 = 3165;
   T quantity = "0.001".to!T;
   T amount = price_per_m3 * quantity;
   writefln ("%.2f %.24f", amount, amount);
}

void main ()
{
   calculate!decimal32;
   calculate!decimal64;
   calculate!decimal128;
   calculate!float;
   calculate!double;
   calculate!real;
}



Re: Is using floating point type for money/currency a good idea?

2019-05-20 Thread Era Scarecrow via Digitalmars-d-learn

On Monday, 20 May 2019 at 12:50:29 UTC, Simen Kjærås wrote:
If you're worried that $92_233_720_368_547_758.07 (long.max) is 
not enough money for your game, I'd note that the entire 
current world economy is about a thousandth of that. Even so, 
there's std.bigint.BigInt, which has no set limit, and can in 
theory represent every whole number up to about 256^(2^64), or 
about 4 quintillion digits. You will encounter other problems 
before this limit becomes an issue.


 Yes at that point BigInt would be a better solution.

 I made a NoGC fixed int type that would allow you to have any 
sized int (once defined, Cent anyone?) and only use stack 
data/space for calculations; It did fairly decently 
performance-wise (still need to do the special assembly 
instructions for supported 128/256 cryto stuff for faster speed 
on supported hardware), but otherwise it worked. Truthfully 
working around with the registers and carry and other details can 
be a chore, though only on divide, everything else is 
straightforward.


 H going with numbers very very very very large would 
probably be more idle games more than anything else. Though I'm 
not sure if many need actual precision (as after you're over say 
E+10 over what you used to have, what you buy isn't really 
relevant til it starts getting only e+4 off; So even rounding 
errors wouldn't matter much. Not sure what format those games 
use. Tempted to believe it's a two pair int (one for exponent and 
one for currency, letting you get E+4billion, would be easy to 
code and do calculations overall, i don't see BigInts being used 
everywhere)


Re: Is using floating point type for money/currency a good idea?

2019-05-20 Thread Era Scarecrow via Digitalmars-d-learn

On Monday, 20 May 2019 at 11:50:57 UTC, Dennis wrote:
For a simple game, I think it's the easiest to just store an 
integer of cents (or the lowest amount of currency possible).


 Back in 2003 i did this very thing for when creating my C 
program for suggesting and helping with credit card payments, so 
it could make suggestions of which ones to pay off in what 
amounts, as i found using float to be too unreliable.



Another option could be to use floats to a very limited state, 
say after calculations (cay calculating interest) you could 
convert to an int then back to float. (money = cast(float) 
(cast(int)money*100) /100)) to get as clean/close to the proper 
value as you can. (Though you may still end up off by a fraction 
of a penny).


Josh's suggestion is close:

 writefln("%f", cast(float) i / 100.0);

The format should be "%f.2", which should do fine for your 
purposes as it would round to the correct value (unless you're 
working with numbers over say 16Million, then float will start 
giving issues, and doubles might be needed).



A third option could be to make your own type, a fixed precision 
int, which would be a struct that you determine precision by some 
arbitrary means (bits, digits, etc) and then do your tostring 
method to handle output appropriately. Not the best, but it would 
also work.


I suppose the last method would be to make a BCD (Binary Coded 
Decimal) type. This is used in calculators (and 8bit BASIC) where 
it's a 6 byte value where every nibble (4bits) is a digit. The 
first byte is the exponent (+/- 128) and 5 bytes store 10 digits 
of data allowing VERY precise values. But the overhead and setup 
seems a bit impractical outside of emulation.



The easiest i would think is just consider the currency a whole 
number, and if you are working with fractions, only do the 
conversion when printing/outputting.


Re: Is using floating point type for money/currency a good idea?

2019-05-20 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Monday, 20 May 2019 at 12:50:29 UTC, Simen Kjærås wrote:
There are some caveats when using doubles, as floating-point 
math is not always equal to regular math. For instance, if you 
had the entire world economy in one variable, you could 
subtract a cent at a time without the variable decreasing. If 
these cents were simultaneously added to a different variable 
(to represent a transaction), this would be an infinite source 
of money.


Yes, but it is fine until  2^53 which is the number 
9007199254740992.  So better than 31 bit ints and only slightly 
worse than 63 bit (signed).


Doubles behave like like integers from 0 up to 2^53 for addition, 
so if you do cents in double then you also get accurate 
representation of cents while also getting decent fractional 
representation when converting to another currency.


If it is important for the game to not leak resources then I 
guess you would have to recalibrate the system from time to time. 
It might be hard to find where money leak. Integers have the same 
problem, however.



If it is a game, you might want to use the same storage-type and 
system for all countable resources, though. Then you could do 
something more advanced and memory efficient, either one storage 
object per owner, or as a global database object.


So if you have lots of (unlimited) resource-pools (accounts, 
bottles, containers etc) to track you could to create your own 
"bank" or "wallet" as an in-memory database which uses variable 
length data records with encapsulated memory management on a 
local heap. So if you have 200 units it uses 1 byte more than an 
empty account, if you have a billion units it uses 4 bytes, a 
trillion units uses 5 bytes, 1000 trillion units use 7 bytes more…


One advantage of using a "bank" is that you can ensure that 
resources don't leak as you have to set up a "transaction" 
between "accounts". (the same amount of money/resources are both 
added or removed  at single point). Less error-prone.


If it is a simulation game then it would also be easier to create 
logs that are useful for debugging/balancing if you have a 
mandatory "transaction" concept (you get a single point where all 
a transactions have to pass, and there you can log it).



Anyway, lots of options. Have fun!



Re: Is using floating point type for money/currency a good idea?

2019-05-20 Thread Simen Kjærås via Digitalmars-d-learn

On Monday, 20 May 2019 at 11:10:32 UTC, Boqsc wrote:

https://dlang.org/spec/float.html

I'm frozen in learning basics of D lang since I want to create 
a simple game and I really would like a clean and simple code, 
however to me floating points are magic.


https://wiki.dlang.org/Review_Queue
Since std.decimal is still work in progress and apparently its 
development is stuck for a while, should I just somehow use 
floating point to store currency or wait until Decimal package 
will be finally included into std Phobos of D lang?


For a simple game storing money in cents, as an int or long, is 
perfectly fine.


If you're worried that $92_233_720_368_547_758.07 (long.max) is 
not enough money for your game, I'd note that the entire current 
world economy is about a thousandth of that. Even so, there's 
std.bigint.BigInt, which has no set limit, and can in theory 
represent every whole number up to about 256^(2^64), or about 4 
quintillion digits. You will encounter other problems before this 
limit becomes an issue.


Depending on the scale and required accuracy, you could also 
perfectly well use doubles. Doubles can accurately represent up 
to about half the world economy in cents. There are some caveats 
when using doubles, as floating-point math is not always equal to 
regular math. For instance, if you had the entire world economy 
in one variable, you could subtract a cent at a time without the 
variable decreasing. If these cents were simultaneously added to 
a different variable (to represent a transaction), this would be 
an infinite source of money. In the same vein, it's possible for 
(a+b) != ((a-x)+(b+x)) if a and b are wildly different in size. 
For a game, this is very unlikely to be a problem, but would 
certainly be worth considering for a real-world application.


For almost every application, a long representing the number of 
cents should cover almost every situation, and is very easy to 
reason about, so I would definitely recommend that. This decision 
could cause overflow issues in some rare cases, and calculating 
interest on extreme values could be slightly inaccurate depending 
on how you do it, but those situations are extreme enough that 
you can reasonably expect them to never happen.


The one case where floating-point almost invariably will enter 
the picture is foreign exchange - the value of one unit of one 
currency in some other currency will only very rarely be a whole 
number.


--
  Simen


Re: Is using floating point type for money/currency a good idea?

2019-05-20 Thread ag0aep6g via Digitalmars-d-learn

On 20.05.19 13:47, Josh wrote:
Normally I would say no, no and no.  Rounding issues will kill you every 
time.


And you'd be right.


  However:

import std.stdio;
import std.range;

void main()
{
 foreach (i; iota(1, 1000)) {
     writefln("%f", cast(float) i / 100.0);
 }
}

Doesn't show any rounding issues, but you still might hit them at large 
values...I just remember back in the day having numbers like 
0.199, but maybe that problem has been solved.


That "problem" hasn't been solved. It can't be solved. `1 / 100.0` might 
print as 0.01, but it isn't exactly 0.01. The output is just rounded. If 
you add more decimals (e.g. `writefln("%.20f", ...)`), those niners will 
show up.


Aside from large and small values, you'll also see significant 
(accumulated) rounding error when doing many operations on your numbers. 
For example, if you add 0.1 ten thousand times, you might expect the 
result to be 1000, but with `float` it's not that:


import std.stdio;
void main()
{
float x = 0;
foreach (i; 0 .. 10_000) x += 0.1;
writeln(x); /* Prints "999.903". */
}

What would be safer is to do "fixed point" math, i.e. use an integer and 
when displaying the value convert it to float and divide by 100.  So if 
the user has 50 cents they internal value would be 50, if you give them 
a dollar twenty five (125) then they would have 175, and when you go to 
display it, dividing by 100 will display 1.75.


Yup.

As long as you are not multiplying money by money you will be fine.  50 
cents times 5 is 2.50 (50 * 5 = 250), however 50 cents times 50 cents is 
2500, which makes no sense but so does multiplying money by money...


50 cents times 50 cents is 2500 square cents. Makes perfect sense.


Re: Is using floating point type for money/currency a good idea?

2019-05-20 Thread Dennis via Digitalmars-d-learn

On Monday, 20 May 2019 at 11:10:32 UTC, Boqsc wrote:
I'm frozen in learning basics of D lang since I want to create 
a simple game and I really would like a clean and simple code,


For a simple game, I think it's the easiest to just store an 
integer of cents (or the lowest amount of currency possible). 
Then storing, adding and comparing just works. Only when you want 
to show it to the user you need some special logic:


```
void printMoney(int cents) {
writeln("You have $", cents / 100, ".", cents % 100);
}
```

If currency is very prevalent or you like to abstract it, you can 
take a look at dub packages aimed at money/decimal types (or 
write your own if existing libraries don't suit your needs).


http://code.dlang.org/packages/money
http://code.dlang.org/packages/stdxdecimal
http://code.dlang.org/packages/decimal
http://code.dlang.org/packages/fixed


Re: Is using floating point type for money/currency a good idea?

2019-05-20 Thread Josh via Digitalmars-d-learn

On Monday, 20 May 2019 at 11:10:32 UTC, Boqsc wrote:

https://dlang.org/spec/float.html

I'm frozen in learning basics of D lang since I want to create 
a simple game and I really would like a clean and simple code, 
however to me floating points are magic.


https://wiki.dlang.org/Review_Queue
Since std.decimal is still work in progress and apparently its 
development is stuck for a while, should I just somehow use 
floating point to store currency or wait until Decimal package 
will be finally included into std Phobos of D lang?


Normally I would say no, no and no.  Rounding issues will kill 
you every time.  However:


import std.stdio;
import std.range;

void main()
{
foreach (i; iota(1, 1000)) {
writefln("%f", cast(float) i / 100.0);
}
}

Doesn't show any rounding issues, but you still might hit them at 
large values...I just remember back in the day having numbers 
like 0.199, but maybe that problem has been solved.


What would be safer is to do "fixed point" math, i.e. use an 
integer and when displaying the value convert it to float and 
divide by 100.  So if the user has 50 cents they internal value 
would be 50, if you give them a dollar twenty five (125) then 
they would have 175, and when you go to display it, dividing by 
100 will display 1.75.


As long as you are not multiplying money by money you will be 
fine.  50 cents times 5 is 2.50 (50 * 5 = 250), however 50 cents 
times 50 cents is 2500, which makes no sense but so does 
multiplying money by money...




Is using floating point type for money/currency a good idea?

2019-05-20 Thread Boqsc via Digitalmars-d-learn

https://dlang.org/spec/float.html

I'm frozen in learning basics of D lang since I want to create a 
simple game and I really would like a clean and simple code, 
however to me floating points are magic.


https://wiki.dlang.org/Review_Queue
Since std.decimal is still work in progress and apparently its 
development is stuck for a while, should I just somehow use 
floating point to store currency or wait until Decimal package 
will be finally included into std Phobos of D lang?