Feature - Rejected (Big)Decimal DataType

Are you interested in a decimal DataType being added to ASH?

  • Yes

    Votes: 2 22.2%
  • No

    Votes: 7 77.8%

  • Total voters
    9

Catch-22

Active member
So, I don't really know if there is much interest in any of the devs implementing this so I wasn't really sure if I should put this thread in scripting discussion, unofficial builds, or here.

Would there be any interest in a decimal DataType being added to ASH? Take careful note, I'm not suggesting the removal/replacement of floats, rather the addition of a new DataType.

Also note, this is not a thread for decimal/float bashing.

If there's enough interest from the community and little interest from the devs, I may set about doing this myself.

Edit: Only if I have the blessings of the devs, I am not interested in fracturing the codebase.

Edit 2: Also feel free to convince me that this is a good/bad idea, and why, with the exception of bashing (please don't bring up arithmetic performance, float and decimals are different tools for different jobs).
 
Last edited:

roippi

Developer
I'm fine with it as an additional datatype. Though it feels really weird to have access to BigDecimal but not doubles.
 

jasonharper

Developer
A higher-precision decimal format would be useful to reduce inaccuracies, but the only one that would be reasonable for ASH would be doubles, in order to exactly match the inaccuracies of the game's calculations.

A longer integer format would be useful in the rare cases where huge values need to be expressed accurately, such as substat points past level 216, but none of these cases would appear to benefit from fractional values.

BigDecimal solves no actual problems that we have.
 

Catch-22

Active member
A longer integer format would be useful in the rare cases where huge values need to be expressed accurately, such as substat points past level 216, but none of these cases would appear to benefit from fractional values.

Yes, or for representing huge amounts of meat (such as the total value of your store if you set everything to 999,999,999). Long is already a DataType used internally in KoLmafia for a small number of things, exposing this to ASH would be fairly simple.

Jason, are you able to go into further detail as to why you don't think it would solve any problems?

Let's say I have an ASH script that tells you your average substat gain over the amount of adventures you spend.

If I spend 5 adventures and get 2, 2, 4, 3 and 5 substats respectively the average comes to 3.2 exactly. Let's compare the following:

Code:
integer: 3
float:   3.200000047683716
double:  3.20000000000000017763568394003
decimal: 3.2

I can see that double is a lot more accurate when compared to float, but still nowhere near as accurate as decimal.
 

Catch-22

Active member
You don't need infinite precision for that, just rounding and leading-zero trimming.

Indeed, this is very true and I have already written a function in ASH that would handle it perfectly. Why should this be necessary, though? When given an option, would it not be better to use the appropriate DataType and forego the formatting?
 

roippi

Developer
Why should this be necessary, though?

The same reason that you don't use BigDecimal as your sole datatype for every variable. You don't need a cannon to kill a mosquito.

If you don't need infinite precision, using a datatype that has infinite precision just so that you don't need to bother with formatting is lazy coding. And I don't mean this in a pejorative sense - if we don't have the right formatting tools available in ASH, we should make them. Jason just added an overridden to_string() that should help.
 
Last edited:

roippi

Developer
Could not the same argument be made against floating points?

No?

Use a float if you need a few significant figures of precision. Use a double if you need many significant figures of precision. Use a BigDecimal if you need a ridiculous level of precision. Or, to be more fair, use it if you need perfect precision, across an arbitrarily large range of significant figures.
 

Veracity

Developer
Staff member
I always liked bignums and ratios in Common Lisp. I actually implemented them in a different version of Lisp. (This is why we have floor, ceiling, truncate, and round, by the way - those were all in CL, even though "truncate" in Java - and therefore, in ASH - is, essentially, "to_int")

bignums are arbitrary precision integers. ratios are a numerator and a denominator of bignums. We did not have "BigDecimals", which are, near as I can tell, bignums + a 32-bit scale factor. Which is to say, not QUITE as versatile as bignums + ratios...

I question whether we need them in ASH.

Have any Use Cases for ASH? Keep in mind that KoLmafia itself stores values in Java floats and 32-bit ints. You want 64-bits of Meat? That's not only a change in ASH, it's a change in KoLmafia's internal handling of Meat.
 

Catch-22

Active member
Use a float if you need a few significant figures of precision. Use a double if you need many significant figures of precision. Use a BigDecimal if you need a ridiculous level of precision. Or, to be more fair, use it if you need perfect precision, across an arbitrarily large range of significant figures.

Alright at the risk of derailing the thread I will summarise that whilst you are not opposed to the implementation of alternative DataTypes, you see no practical use for using perfectly accurate numbers in KoLmafia calculations. Thanks roippi :)
 

Catch-22

Active member
Have any Use Cases for ASH? Keep in mind that KoLmafia itself stores values in Java floats and 32-bit ints. You want 64-bits of Meat? That's not only a change in ASH, it's a change in KoLmafia's internal handling of Meat.

I'd love 64-bits of Meat :D but no, not exactly. The meat cap is 2^32 anyway, so you wouldn't need to change the internal handling of meat. An existing use case would be the networth.ash script, whilst BoozerBear doesn't have any more meat on hand than 2^32, I'm sure his networth would overflow a 32-bit integer quite a few times, alas that would also be a case for long integers.

Let's take that case a little bit further and say I wanted to (accurately) work out how much BoozerBear would be worth, then how much each player in the Kingdom would receive if he were to liquidate his entire asset portfolio and distribute the wealth amongst the playerbase evenly.
 

Veracity

Developer
Staff member
The meat cap is 2^32 anyway, so you wouldn't need to change the internal handling of meat.
That is a 32 bit unsigned integer. Java, unlike C, does not have "unsigned" ints. A java "int" is 32 bits signed. In order to get a 32-bit unsigned quantity, we would have to move to a Java "long".

Which is to say, yes, we most certainly would have to change the internal handling of meat.

Additionally, in ASH, all functions that take meat use an "int", which is currently defined to be a Java "int". We could define an ASH "int" to be a Java "long" - much as we could change an ASH "float" to be a Java "double".

I did the latter, a number of years ago in Revision 407 on May 10, 2006. Hola changed ASH floats back to being Java floats in Revision 1399 on September 2, 2006; he reverted my change.
 
Last edited:

Catch-22

Active member
That is a 32 bit unsigned integer. Java, unlike C, does not have "unsigned" ints. A java "int" is 32 bits signed. In order to get a 32-bit unsigned quantity, we would have to move to a Java "long".

Which is to say, yes, we most certainly would have to change the internal handling of meat.

Additionally, in ASH, all functions that take meat use an "int", which is currently defined to be a Java "int". We could define an ASH "int" to be a Java "long" - much as we could change an ASH "float" to be a Java "double".

Ah, in that case shouldn't we be handling meat as a long value anyway?

Consider (my_meat() + my_closet_meat()), where the player has the 2^32 meat in each, currently this equates to -2 meat. Perhaps a new feature request for ASH "int" to be defined as Java "long" is in order? That doesn't really have much to do with BigDecimal support, but I would also be in favour of long support.
 

xKiv

Active member
Use a float if you need a few significant figures of binary precision. Use a double if you need many significant figures of binary precision. Use a BigDecimal if you need any non-zero figures of decimal precision.

FTFY.
I don't need to perfectly represent 1.2349629374527934592346523475982543619439867249573246572346523458.
I don't need to perfectly represent 1/3 (that might be theoretically nice to have, but there's only no difference between theory and practice in theory, not practice).

I want to perfectly represent 1.2.
I want this to return true (I am doing this in C, but the IEEE-defined binary [1] floats are the same):
Code:
float a = 1.2;
float b = 6;
return a*5==b;
(note: if I write 1.2*5==6, it returns true because the compiler (gcc in my case) optimizes the arithmetic away without actually representing them as floats, so the result of the computation is not the same as it would be in run-time ... just the same kind of insidious stuff that I would like to avoid, and no amount of binary floating-point precision will help).
(if you are curious, on my computer a*5>b)

Thank you.

[1] funny thing, there actualy *are* BCD floats defined by IEEE, and as far as I can tell, they are even implemented in x86 FPUs, just not supported in programming languages, and probably significantly inferior in performance.
 

roippi

Developer
I want this to return true

Code:
float a = 1.2;
float b = 6;
return MyFloatFormatter.format( a*5 ).equals( MyFloatFormatter.format( b ) );

We keep asking for a use case. A use case for longs was presented instead. I support adding longs to ASH and/or changing the backend for how we store meat values.
 

xKiv

Active member
Your "workaround" will fail to work around accumulated error after many calculations. Are you really suggesting that anyone who wants numbers to behave should re-normalize them (after each operation%2
 
Last edited:

fronobulax

Developer
Staff member
you see no practical use for using perfectly accurate numbers in KoLmafia calculations.

I'm sorry, but anyone who uses the phrase "perfectly accurate" when describing computer calculations either has their tongue firmly in cheek or lacks some basic understanding of numerical analysis or whatever term one might use to describe computational mathematics using a computer.
 

xKiv

Active member
In unrelated news, does this forum have a "revert edit" option somewhere? Seems like vBulletin ate most of my previous post when my connection dropped halfway through submitting a one-line edit.

If not, there was something about how there are better reasons not to implement this (like "no dev wants to do this", "it would complicate ASH parsing code" (I vaguely remember Veracity using this as an argument against adding more types?), "it would actually make some calculations wrong (compared to kol's implementation in PHP)", ...).
Something about some reasons not being good at all (c.f. "mafia already does this, there's no reason to ask for it it in vanilla kol too!")
Also something about fugly/unreliable explicit workarounds (that are worse in every usability way).
Also something about people who would no longer get confounded by numbers behaving insidiously different from most people's expectations (no more a+1==a, no more (a/b)*b!=a, no more having to pretend that your numbers are correct by printing different numbers ...)
The edit in question was "(ETA: I guess what I was trying to get at with at least some of that is 'cure the problem, not the symptom')".
 
Top