Two Decimal Place Fixed Point Decimals a Necessary Feature

For basic accounting in all countries that use a decimal currency, such as Dollars and Cents, all numbers are always two decimal places.

For this reason, having a financial number type, that is always two decimals, would be extremely valuable, and should be a built in feature.

Why? Perfectly fine, actively maintained packages exist already, eg

19 Likes

The way I’d go about this would probably be to build a package on top of Unitful.jl that would let you handle numbers with a unit of dollars, or cents, or 1/16th of a cent, or whatever you prefer.

Not only would that ensure correct rounding, but it would also prevent coding errors, such as adding a number of euros to a number of dollars without first applying an exchange rate.

3 Likes

I’ll have to look into that. I don’t need conversion for what I’m doing, but I was thinking of making a package, and there it would be useful. It could also be useful for inventory, and accrual accounting.

For basic accounting in all countries that use a decimal currency, such as Dollars and Cents, all numbers are always two decimal places.

This is mostly —but not generally— true; some of the Gulf states (Bahrain, for example: 1 dinar =1000 fils) use three decimal places in their currencies.
As mentioned already, DecFP.jl is probably the way to go, as this uses Intel’s Decimal Floating-Point Library which is intended for legally-regulated financial arithmetic.
Disclaimer: I don’t know the details of what you’re trying to do or the legal regulations and jurisdiction in which you’re operating; it’s up to you to check what applies in your case(s).

1 Like

Just use Decimal Floating Point with 200 decimal digits like this

julia> using DFPs
[ Info: Precompiling DFPs [top-level]

julia> DFP_setDefaultPrecision(200)
200

julia> a = DFP(Ď€); DFP_toCommonString(a)
"3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303820"

julia> b=a^a^a; DFP_toCommonString(b)
"1340164183006357435.2974491296401314150993749745734992377879275165860340926190940681482694726113011422734374889525974969490984456374683189320748144171329686859566550586183230440926034493572213761908396"

julia> c = DFP("0.01") + DFP("0.02"); DFP_toCommonString(c)
"0.030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"

You see 200 decimal digits in decimal floating point should be enough even for the Federal Reserve of USA.

Umm… pretty sure they’d be fine with 20 or at most 30. The entire GDP is only 10^13 or so. Even the net market value of all assets is probably only 10^3 times that big (the US is less than 300 years old).

2 Likes

Umm… pretty sure they’d be fine with 20 or at most 30. The entire GDP is only 10^13 or so. Even the net market value of all assets is probably only 10^3 times that big (the US is less than 300 years old).

But what if you want to model the economy of USA , 1000 years into the future? With hyperinflation… when they start coming for your GOLD.

If you want to model things then binary floats are fine, and you can nondimensionalize the problem with all dollars as a fraction of GDP. It’s only if you want to record legal transactions that you need decimal floats :wink:

But it made me chuckle. thanks.

3 Likes

But I want to model it accurate down to the last cent.

I like doing stuff like this

julia> 666.66 ^ 777.77
Inf

julia> d = DFP("666.66") ^ DFP("777.77"); DFP_toCommonString(d)
"2.2290695290173413346892956756741292206624583124046169287860844720642750156423246050757086944529571798897824685796704570535219728601085970863260994593278212928618633515968324077642684223432198762330306E2196"

julia> DFP_toShortCommonString(d)
"2.22907E2196"
1 Like

:rofl:

Currency exchange rates are listed on the Oslo Børs with five decimal places. And I think I’ve seen accounting with 1/1000 Norwegian krone.

Do I do DPF() until I’m done arithmetic, then add a string to the DataFrame?

I don’t understand your question.

You enter all your values into DFP types and do your arithmetic using DFP

julia> using DFPs

julia> DFP_setDefaultPrecision(200)
200

julia> a = DFP("1.23"); b= DFP("23.456"); c= a * b + a;

julia> DFP_toCommonString(c)
"30.080880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"

julia> c_rounded = round(c,digits=2); # rounded to the nearest cent

julia> DFP_toCommonString(c_rounded)
"30.080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"

You can find the source for DFPs module version 1.2.6 here. You have to go to the website and manually copy the source code, it is not in a repository. Don’t worry it is all in a single file called DFPs.jl

I put my modules in my path this way. Then I put a symbolic link inside the mymodules directory to the actual location of the module file.

$ cd ~/.julia/

$ cat config/startup.jl
push!(LOAD_PATH, "/Users/ssiew/.julia/mymodules/")

$ ls -l /Users/ssiew/.julia/mymodules/DFPs.jl 
lrwxr-xr-x  1 ssiew  staff  36 18 Jul  2020 /Users/ssiew/.julia/mymodules/DFPs.jl -> /Users/ssiew/juliascript/DFP/DFPs.jl
3 Likes

DFPs won’t load for me. Do I need to put in an address?

I think I can test how to use DecFP, but I want to make sure everything. I didn’t see any other documentation like tutorials? This might help some rounding problems, but I’m not finding a way to actually round.

That’s because DecFP uses exactly the same functions as those in Julia’s standard library, once you’ve constructed a DecFP number. This is part of the beauty of multiple dispatch—the package just adds methods to the existing functions to handle the new type. Here, you call the round function:

julia> using DecFP

julia> x = d"15.3412"  # constructs a 64-bit decimal float, representing 15.3412 exactly
15.3412

julia> round(x, digits=2)
15.34

julia> typeof(ans)
Dec64

Note that it implements “banker’s rounding” (i.e., round-to-even) by default, although there are other rounding modes available:

julia> round(d"15.345", digits=2)
15.34

julia> round(d"15.355", digits=2)
15.36
5 Likes

Yes this appars to work, it doesn’t seem to display 2 digits, but that’s not a big issue. If I save to to PostgresSQL and load the DBs into Libre Office, then I could probably set Calc to two digits, then it would be good all the time.

I am not sure why you expect it to do that, it is a generic decimal floating point library. If you round before printing, it should work fine, also AFAICT with printf, eg

julia> @sprintf("%0.2f", d"123.456")
"123.46"
2 Likes