January 02, 2020
On Thursday, 2 January 2020 at 21:31:02 UTC, JN wrote:
> On Thursday, 2 January 2020 at 21:03:42 UTC, bachmeier wrote:
>> Okay, I'm not a Lua expert, obviously. The point still stands that you can have a successful programming language without even having an integer type.
>
> *cough* *cough* JavaScript *cough*

JavaScript has 32 bit integers as an implict type though.


January 02, 2020
On Thursday, 2 January 2020 at 19:59:09 UTC, Ola Fosheim Grøstad wrote:
> On Thursday, 2 January 2020 at 19:25:08 UTC, Ola Fosheim Grøstad wrote:
>> (123*3+50)/100... Or 3.14% of 123 as (123*314+5000)/1000.
>
> So easy to make mistakes with fixed point, should've been /10000...
>

The devil goes even further if you want to account for negative numbers :)
Integer rounding is actually kind of hellish vs floating-point rounding.
January 02, 2020
On Thursday, 2 January 2020 at 18:26:25 UTC, Ola Fosheim Grøstad wrote:
> 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.

For the curious, on some FPUs you can test if the computations was inexact using the FE_INEXACT flag. So, then you can do all the computations and ensure that there is no information loss up to the division. Then you do an inexact division with rounding-down mode:

// set rounding down mode here and track FE_INEXACT exception
x = 3.0*value+0.5

// ensure that  FE_INEXACT is false

// do inexact computation
result = floor(x/100.0)

I think that should work out ok for all input values, but I've never actually used FE_INEXACT in practice, so maybe I got something wrong...


January 03, 2020
On Thursday, 2 January 2020 at 23:13:00 UTC, Ola Fosheim Grøstad wrote:
> // set rounding down mode here and track FE_INEXACT exception
> x = 3.0*value+0.5

x = 3.0*value+50.0 … ;-)


In addtion to the IEEE754 base10 D-implementation that exists as a dub package I found this implementation by Intel:

https://software.intel.com/en-us/articles/intel-decimal-floating-point-math-library

Clock cycle counts from 2018:

https://www.lirmm.fr/arith18/papers/CorneaM_Decimal_ARITH18.pdf

It apparently supports Linux, Windows and Mac so it might be worth creating bindings for it if nobody has done it already?

This combined with IEEE1788 could be interesting, first do the computation with base2 hardware floats and revert to base 10 on failure.

Base 2 is basically 100 times faster...

January 03, 2020
On 1/1/20 4:06 PM, Steven Schveighoffer wrote:
> On 1/1/20 3:20 PM, Ola Fosheim Grøstad wrote:
>> On Wednesday, 1 January 2020 at 19:01:36 UTC, Steven Schveighoffer wrote:
>>> That is what I use. Fixed point with a factor of power of 10. In other words, a fixed point number with 2 decimal places would be sufficient for such currency. When doing math on such types, you just need to deal with the underlying numbers, and it works fine.
>>
>> You don't need fixed point, just store cents in 64 bit floating point and you get at least the same accuracy as a 53 bit integer fixed point.
>>
> 
> It is stored that way. Stored as a long. Just nicer to deal with printing and such. And instead of having to remember the factor, it's stored with the type.

oops, totally misread the floating point part, I thought you said 64 bit integer.

It's not a *terrible* idea, but as you accumulate more errors, they will add up. In money transactions, most of the time you have a fixed resolution, and everything is rounded at every transaction. So floating point is not necessary. I'd much rather do integer. I like the exactness, and with something like checkedInt, you shouldn't have overflow problems.

-Steve
January 03, 2020
On Friday, 3 January 2020 at 14:49:34 UTC, Steven Schveighoffer wrote:
> It's not a *terrible* idea, but as you accumulate more errors, they will add up.

I actually use base10 on the server, out of convenience and easy maintenance, but my point is that you don't have to as long as you understand what is going on under the hood.

You won't get more than a cent error and very rarely, even when you don't set the rounding mode if you think about how floating point works. And one cannot set the rounding mode in JavaScript, so that is what you have to deal with. But it depends on what you do. Nobody are going to complain that they get one cent less on the invoice than in the "web shop pricing estimate".

> In money transactions, most of the time you have a fixed resolution, and everything is rounded at every transaction. So floating point is not necessary.

Ok, so there you have a use case. If you only add then it is no problem, but if you do more complex calculations and more complex rounding then it becomes tedious and error prone real fast.

When you add various layers of rebates and sales tax and what not it can get tricky to be certain that you will stay within a fixed bit width.

If the owner of the system is ok with giving a little more rebate (like a cent) then fixed point does not look like a good solution.

> I'd much rather do integer. I like the exactness, and with something like checkedInt, you shouldn't have overflow problems.

Well, but how do you know that you have enough bits and how do you account for an unknown number of digits at compile time if the end user can type in several rebate multipliers? If you get an exception you still have a problem...?

In the general case you basically need to use big-int, and then you might as well do base 10, IMHO.

January 03, 2020
And please forget the idea that fixed point is exact, it most certainly is not! :-)

Let me give an example:

Assume that you have 21% VAT and prices are given including tax, then in order to find the price without VAT you have to calculate price/1.21, but in fixed point that becomes price*100/121 which will have a remainder. So then you also have to deal with the remainder, so not exact at all.

If you want the price without VAT, rounded you'll have to do:

   (price * 200 / 242 + 1) / 2

If you want to deal with the price without VAT with no rounding, you will have to emulate rational numbers...


January 03, 2020
On 1/3/20 12:14 PM, Ola Fosheim Grøstad wrote:
> And please forget the idea that fixed point is exact, it most certainly is not! :-)

Exactness according to the terms of what is agreed upon for discrete units. Not according to some IEEE standard where the discreteness varies based on value.

If you want complete exactness, rational numbers are what you need, and I do use those in other places.

> 
> Let me give an example:
> 
> Assume that you have 21% VAT and prices are given including tax, then in order to find the price without VAT you have to calculate price/1.21, but in fixed point that becomes price*100/121 which will have a remainder. So then you also have to deal with the remainder, so not exact at all.
> 
> If you want the price without VAT, rounded you'll have to do:
> 
>     (price * 200 / 242 + 1) / 2
> 
> If you want to deal with the price without VAT with no rounding, you will have to emulate rational numbers...
> 
> 

You are starting from an inexact figure to begin with (almost certainly it has been rounded). Of course your figures will not be exact, in any number system.

If tax is added on top of the total taxable cost, then a per-item cost is going to be inexact anyway (some will have one extra cent added due to the rounding).

Generally you are only dealing with transaction amounts in full cents, unless there is some electronic form of payment, and in that case, you have a limit as to what you are dealing with. I'll take inexactness based on rounding, but consistent and agreed upon rules, over inexactness of actual value, any day.

I'll give you an example, you go to the store and an item is on sale for 3 for $5.00. The cost for the first item is $1.67, the cost for the second item is $1.67, the cost for the third is $1.66. Total is $5. But if you buy one item, it's $1.67. I can understand the rules without any issue. I can't tell you what happens when you multiply 5.0/3.0 * 3.0 (or even 500.0/3.0 * 3.0). Most likely it's fine, but I can't tell you that for sure it is going to be fine.

You can create systems that have rules for how to deal with imprecision, but you need to base it on types that are easy to predict and don't require IEEE experts to understand.

-Steve
January 03, 2020
On Friday, 3 January 2020 at 17:45:44 UTC, Steven Schveighoffer wrote:
> If tax is added on top of the total taxable cost, then a per-item cost is going to be inexact anyway (some will have one extra cent added due to the rounding).

Yes, although in Norway you have to give prices including VAT to consumers, but not to businesses where excluded VAT is the norm. So to get nice looking figures like "9.90" to consumers or to businesses you can either set the price including/excluding VAT and calculate the other unit doing multiplication/division.  (The "law" is that the VAT is added, but that is only in book keeping).

> You can create systems that have rules for how to deal with imprecision, but you need to base it on types that are easy to predict and don't require IEEE experts to understand.

In that case you have to rule out fixed point and you'll have to settle for a large base 10 type.

I think that is going a bit far.  In my book it all depends on the situation, and the programmer is obviously part of that, but so is the platform (e.g. javascript), laws and regulations, whether it is for estimates or invoices, if it is used for accounting or sales pitch, etc etc.

January 04, 2020
On Friday, 3 January 2020 at 17:14:06 UTC, Ola Fosheim Grøstad wrote:
> If you want the price without VAT, rounded you'll have to do:
>
>    (price * 200 / 242 + 1) / 2

Hah! Another fixed point mistake!!  It should have been:

   (price * 200 / 121 + 1) / 2

This is what makes fixed point a chore, it is hard to read and tricky to maintain, even when it was easy to write...