Bug - Fixed Irregular handling of floats in modifier_eval

Theraze

Active member
Except that floats are also used for big numbers, not just small ones... for example, in the omnivore script where it calculates out how much total it will cost you to consume everything, with multiple drinks priced at mall-max of 999 million, it passes int-max when the third is added. While BigDecimal would allow for precise <1 calculations, it won't help with the other category, that of large numbers, currently handled by floats and which was also affected by the scientific notation...

Thanks for the fix to this bug report, jason. Hope Bale's bug report is able to be closed soon as well.
 

Catch-22

Active member
Except that floats are also used for big numbers, not just small ones... for example, in the omnivore script where it calculates out how much total it will cost you to consume everything, with multiple drinks priced at mall-max of 999 million, it passes int-max when the third is added. While BigDecimal would allow for precise <1 calculations, it won't help with the other category, that of large numbers, currently handled by floats and which was also affected by the scientific notation...

You know there's a reason they call it BigDecimal, right?

JavaTM 2 Platform Standard Ed. 5.0 said:
A BigDecimal consists of an arbitrary precision integer unscaled value and a 32-bit integer scale.

I don't know if you specifically have a vendetta against me, for some reason, or if this is just coming across to me the wrong way because it's text on a forum. I've done nothing but try to provide useful information and suggestions but it seems to me that each time I do, you're trying to throw it back in my face.
 
Last edited:

roippi

Developer
Theraze is perhaps overly dismissive and you are perhaps overly sensitive. Chill.

Edit: regarding BigDecimal: the value that ASH is reporting is what kolmafia is internally using - floats. If you are suggesting we switch to BigDecimal to do all our floating point arithmetic: hell no. BigDecimal is over three orders of magnitude slower than primitive type calculations. It's abhorrent.

Also, if a and b are BigDecimals, you can't do a + b. It's a.add( b ). So, imagine the code rewrite.

0.10000000149011612 may feel icky, but that is 0.1 for all intents and purposes. It is formatted like shit, but it's the right number. So if the problem is formatting, we fix the formatter, not the backend for how we do floating point arithmetic.
 
Last edited:

Catch-22

Active member
BigDecimal is over three orders of magnitude slower than primitive type calculations. It's abhorrent.

( ( 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 ) != ( 0.1 * 10 ) ) is abhorrent :p

You're talking about an operation taking 10µs instead of 10ns, so I guess it really depends on what you think is more important: Accuracy, or speed. It's also important to measure these things before assuming they're going to work out slower.

Oh well. I'd be happy to help implement such changes, should it ever be desired.
 

roippi

Developer
I still can't really come up with a use case in mafia for BigDecimal.

Doubles I do see an argument for, we'd just need a bit of creative rounding when printing.
 

xKiv

Active member
BigDecimal might be much slower than float (but not really - I was working on a large banking application where one of the (many) things we did was convert everything from floats to BigDecimals, and it didn't slow down considerably, even with all the new heavy calculations), but for me the worse thing is that you have to explicitly specify rounding mode and scale every time you call divide(), and I would also be wary of memory requirements (more frequent garbage collections, at the very least).

Everything else is handwaveavble or an advantage, imao.
Methods instead of operators: that's change only inside mafia itself, ASH can keep using operators. Not envious of the person coding the change to mafia, though. Unless the only thing changed is ASH's numbers, and mafia keeps using floats everywhere else.
BigDecimal will keep source-specified precision (as long as you initialize it with a String and don't go through an intermediate float, like what confounded me a few times already; right: new BigDecimal("0.1"), wrong: new BigDecimal(0.1));
I suspect ASH (and java itself) has enough overhead that the difference will be significantly smaller than what measuring two tight loops doing nothing else would suggest.

Worst case, we can use BigDecimal just to output doubles at specified precision:
Code:
(new BigDecimal(1234860.43248754324)).setScale(50, RoundingMode.HALF_UP).stripTrailingZeros().toString();
(that 50 is how many decimals (after the decimal point) I want at most, stripTrailingZeroes is there to prevent extra zeroes at the end)
But I would prefer having numbers that exactly represent what I wrote in the code (or in the inpout box) over having unknowably-faster calculations.
I mean, unless we are talking a change from "almost instant" to "minutes", but I am not convinced about that.
 

Rinn

Developer
We're not folding proteins here, I doubt there's any real benefit to having highly exact float values. The strings are never in scientific notation now, that should be enough to not cause massive problems with ash scripts.
 

xKiv

Active member
highly exact float values
I think zou are completelz missing the point. It's not about "exact float values". It's about "exact decimal values". People expect simple calculations to have the results they would show on a hand calculator (or on paper, for people who can still do that). When the computer can't correctly compute something a grade-schooler can, something is wrong.
I am not asking for "500 digits of precision", I am asking for "use the damn numbers I actually wrote". In fact, I could say I am actually asking for "don't introduce inprecision at the 50th digit when I only entered 4 digits".
 

Theraze

Active member
Could we move the discussion on Float v. BigDecimal to its own FReq? It's not directly related to modifier_eval, except in that this bug being closed made it visible. However, modifier_eval, as well as any other function that depended on floats being saved exactly, shouldn't break anymore... the bug is dead. Long live the new FReqs.
 
Top