RFTools

RFTools

74M Downloads

Use decimal, integer, or rational arithmetic in RFTools Spawner

saulrh opened this issue ยท 2 comments

commented

It's been pointed out several times that floats can't properly represent decimal fractions and that the resulting rounding problems cause annoyances in the RFTools Spawner. For example, #1146 and #946. It is correct to conclude that there will always be rounding errors in e.g. 1.0f - 0.1f. However, there are simple arithmetics that could be used that would not have this rounding problem. Several possibilities, some of which wouldn't even require code changes:

  • Work with integers. Multiply all values by the least common denominator among all matter quantities in each category. This could be accomplished without code changes, as IEEE floats perfectly represent the integers in the range [-2^24, 2^24]. Just multiply every matter value in the config file by the least common denominator of all matter amounts so they're all integers. Downside is that many quantities would no longer be exactly one. I argue that this wouldn't make a huge difference; for example, the value of a piece of key matter would indicate how many spawns you can get off a single piece of it.
  • Rational arithmetic. Instead of storing values as floats, store as two integers, a numerator and denominator, and do computations in the space of fractions instead of floats. Example implementation available from rosetta code. Would be slightly more invasive, but would preserve the current fractional values.
  • Fixed-point (decimal) arithmetic. Commonly used in embedded systems that can't do floats efficiently, these permit computation on fractions using an internal representation that is the integers combined with a fixed (often hard-coded) radix. For example, if you chose a base of 1000, you'd store 0.01 as an integer 10 (0.01 == 10 / 1000), do all of your computations in that base, and convert to another representation before outputting the final value. In this case you'd want to choose the base to be a smallish power of ten (1000 or 10000 or so). Rounding errors would still be possible, but as the values you're actually using are all multiples of powers of ten and you can represent exactly multiples of powers of ten, you'd experience no errors.
  • Work with multiples of negative powers of two, which can be exactly represented by binary floats. For example, using binary32 (aka "IEEE float"), 0x3f400000 has the value of 1.5 * 2-1 and is exactly equal to 0.7510. This is essentially rational arithmetic restricted to denominators that are powers of two so that they can be represented using the fact that an IEEE float is mantissa * 2^exponent. Nice and clean from a mathematical perspective, but maybe not so much from a usability perspective? You'd end up with, for example, the spawner consuming 0.125 key matter per spawn (that is, 1 * 2-3 matter) to give exactly 8 spawns per consumed key matter, all possible values represented without error by binary floats.
commented

I don't have a minecraft dev env set up so I can't say anything about whether the patch works, but I can at least reformat it and put it in git so it's readable. It appears to implement proposal 3, fixed-point arithmetic, doing computations in longs with a hard-coded (magic number) scale factor of 2520. 1.12...saulrh:spawner-fixed-point-arith

commented

This patch has been relayed to me by someone without an account. According to them "that version is no longer compatible with rftools original, due changes to packets" but maybe it could be useful, I dunno.