Floating-point inaccuracies permeate the game.

Ideas that are too old (too many things have changed since) and ones which won't be implemented for certain reasons or if there are obviously better suggestions.

Moderator: ickputzdirwech

dupraz
Long Handed Inserter
Long Handed Inserter
Posts: 50
Joined: Fri Sep 01, 2023 6:45 pm
Contact:

Floating-point inaccuracies permeate the game.

Post by dupraz »

As you may know, a burner miner consumes 150 kW of energy to produce one mining operationg every 4 seconds.
Therefore, you might assume that using 600 kJ of energy, you should be able to yield one. Or more practially, that using 3 pieces of coal of 4 MJ each, or 12_000 kJ, a total of 20.
Here is what happens in practice.

factorio_1782510400.png
factorio_1782510400.png (552.48 KiB) Viewed 643 times
There are countless, examples of this happening in nearly every calculation made by the game. Since the game is fixed at 60 UPS, is there any rational whatsoever in the liberal usage of floating-points in every aspects of what should essentially be integer math? I am not filling a bug-report since I already know this will be immediately disregarded as a "won't fix" or "minor" issue.
Rseding91
Factorio Staff
Factorio Staff
Posts: 17017
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Floating-point inaccuracies permeate the game.

Post by Rseding91 »

The game is not fixed at 60 ups, and machines may run faster or slower depending on beacons, modules, and available power. Functionally, these things don’t matter at scale - scale the game heavily encourages and incentivizes.
If you want to get ahold of me I'm almost always on Discord.
radical_larry
Long Handed Inserter
Long Handed Inserter
Posts: 95
Joined: Wed Dec 04, 2024 1:52 am
Contact:

Re: Floating-point inaccuracies permeate the game.

Post by radical_larry »

Rseding91 wrote: Fri Jun 26, 2026 10:03 pm The game is not fixed at 60 ups, and machines may run faster or slower depending on beacons, modules, and available power. Functionally, these things don’t matter at scale - scale the game heavily encourages and incentivizes.
All those factors could still be accounted for in fixed point math. There's no point (ha) in using floating point math in a game engine that is fully deterministic.
I remember a time when Wube tried to program things correctly out of principle.
dupraz
Long Handed Inserter
Long Handed Inserter
Posts: 50
Joined: Fri Sep 01, 2023 6:45 pm
Contact:

Re: Floating-point inaccuracies permeate the game.

Post by dupraz »

radical_larry wrote: Fri Jun 26, 2026 10:16 pm
Rseding91 wrote: Fri Jun 26, 2026 10:03 pm The game is not fixed at 60 ups, and machines may run faster or slower depending on beacons, modules, and available power. Functionally, these things don’t matter at scale - scale the game heavily encourages and incentivizes.
All those factors could still be accounted for in fixed point math. There's no point (ha) in using floating point math in a game engine that is fully deterministic.
I remember a time when Wube tried to program things correctly out of principle.
This is essentially correct, floating-point arithmetic has a very specific use-case, it is also referred to as "scientific computation", because it's supposed to be used when dealing with the analogical measurement of natual phenomena, that is, using sensors of varying degrees of accuracy, that can be estimated to be within error intervals, where the innate inaccuracy of floating-points are meant to be a strict bound for this degree of noise, ie. half-precision (16-bits), full-precision (32-bits), double precision (64-bits), etc. while providing a sufficient dynamic range to remain equally (in relative terms) accurate at small and large scales.

You don't need floating-points to draw a circle using discrete pixels, or to calculate PI within an arbitrary degree of precision, which is how every CAS operates.
zwickau
Burner Inserter
Burner Inserter
Posts: 10
Joined: Fri May 01, 2026 9:39 pm
Contact:

Re: Floating-point inaccuracies permeate the game.

Post by zwickau »

Huh, I'm surprised to see this, I never noticed! I guess I expected that this problem would be magic-ed away somewhere in the background.

I'm not sure if the post author is making this assumption, but: integer division isn't necessarily faster than floating point division. Actually, I think it's usually the case that integer division is the slower operation. Given the importance placed on performance and the ubiquity of such math in the running of the game, it's the clear choice, right?
radical_larry wrote: Fri Jun 26, 2026 10:16 pm
Rseding91 wrote: Fri Jun 26, 2026 10:03 pm The game is not fixed at 60 ups, and machines may run faster or slower depending on beacons, modules, and available power. Functionally, these things don’t matter at scale - scale the game heavily encourages and incentivizes.
All those factors could still be accounted for in fixed point math. There's no point (ha) in using floating point math in a game engine that is fully deterministic.
I remember a time when Wube tried to program things correctly out of principle.
I'm not sure how the game being deterministic is relevant.
Khaylain
Long Handed Inserter
Long Handed Inserter
Posts: 80
Joined: Thu Mar 31, 2016 12:23 am
Contact:

Re: Floating-point inaccuracies permeate the game.

Post by Khaylain »

zwickau wrote: Fri Jun 26, 2026 11:05 pm Huh, I'm surprised to see this, I never noticed! I guess I expected that this problem would be magic-ed away somewhere in the background.

I'm not sure if the post author is making this assumption, but: integer division isn't necessarily faster than floating point division. Actually, I think it's usually the case that integer division is the slower operation. Given the importance placed on performance and the ubiquity of such math in the running of the game, it's the clear choice, right?
radical_larry wrote: Fri Jun 26, 2026 10:16 pm
Rseding91 wrote: Fri Jun 26, 2026 10:03 pm The game is not fixed at 60 ups, and machines may run faster or slower depending on beacons, modules, and available power. Functionally, these things don’t matter at scale - scale the game heavily encourages and incentivizes.
All those factors could still be accounted for in fixed point math. There's no point (ha) in using floating point math in a game engine that is fully deterministic.
I remember a time when Wube tried to program things correctly out of principle.
I'm not sure how the game being deterministic is relevant.
I just took a quick look, and according to https://deepwiki.com/arturbac/fixed_mat ... ting-point it appears that fixed point (not integer) calculations are generally as good or better than floating point calculations.
dupraz
Long Handed Inserter
Long Handed Inserter
Posts: 50
Joined: Fri Sep 01, 2023 6:45 pm
Contact:

Re: Floating-point inaccuracies permeate the game.

Post by dupraz »

Khaylain wrote: Sat Jun 27, 2026 1:12 am I just took a quick look, and according to https://deepwiki.com/arturbac/fixed_mat ... ting-point it appears that fixed point (not integer) calculations are generally as good or better than floating point calculations.
Sounds like a drop-in replacement for the float type that could be used strategically for entity processing time (division) and status effect calculations (multiplication) with no loss of precision nor performance, but which would only give exact results. Do they care enough to try? This requires at least C++ 17.

https://github.com/arturbac/fixed_math

Another solution would be to use the (C++ built-in) integer division operator /= with a fixed resolution, just like is currently used for quality effects, for example using integers shown as multiples of 0.00001 for display, since factorio is a 64-bit game the loss in dynamic range would not be significant. There are many ways to go about solving this.

https://arturbac.github.io/fixed_math/division.html

Decimal floating-points would also work.

It's also fair to mention that binary floating-points (having no practical use-case in the game), is usually non-deterministic across CPUs, and might even be a cause for desyncs.
dupraz
Long Handed Inserter
Long Handed Inserter
Posts: 50
Joined: Fri Sep 01, 2023 6:45 pm
Contact:

Re: Floating-point inaccuracies permeate the game.

Post by dupraz »

Rseding91 wrote: Fri Jun 26, 2026 10:03 pm The game is not fixed at 60 ups, and machines may run faster or slower depending on beacons, modules, and available power. Functionally, these things don’t matter at scale - scale the game heavily encourages and incentivizes.
Are you just going to bury this issue even after practical solutions have been provided to you? None of the concerns you stated are technically relevant, and I don't even see what you mean by UPS not being fixed since 1 second of in-game time is always 60 ticks, no matter the game.speed or how fast your computer runs.
Hurkyl
Filter Inserter
Filter Inserter
Posts: 273
Joined: Mon Dec 02, 2024 10:54 am
Contact:

Re: Floating-point inaccuracies permeate the game.

Post by Hurkyl »

dupraz wrote: Fri Jun 26, 2026 10:27 pmThis is essentially correct, floating-point arithmetic has a very specific use-case,
There is also the very specific use-case of high-performance calculation, since CPUs have the floating-point logic built-in and often have a more robust suite of operations for efficiently working on floating-point values.

I've done work with high-performance integer calculations, and have seen situations where it's actually faster to use the CPU's floating-point logic (carefully managed so that floating point error doesn't occur, or doesn't affect the end result) rather than its integer logic for the exact same sequence of operations.
dupraz
Long Handed Inserter
Long Handed Inserter
Posts: 50
Joined: Fri Sep 01, 2023 6:45 pm
Contact:

Re: Floating-point inaccuracies permeate the game.

Post by dupraz »

Hurkyl wrote: Sat Jun 27, 2026 7:15 pm
dupraz wrote: Fri Jun 26, 2026 10:27 pmThis is essentially correct, floating-point arithmetic has a very specific use-case,
There is also the very specific use-case of high-performance calculation, since CPUs have the floating-point logic built-in and often have a more robust suite of operations for efficiently working on floating-point values.

I've done work with high-performance integer calculations, and have seen situations where it's actually faster to use the CPU's floating-point logic (carefully managed so that floating point error doesn't occur, or doesn't affect the end result) rather than its integer logic for the exact same sequence of operations.
Even if that's the case, it would be a hack based on a quirk of the state of current CPU designs, which isn't even currently implemented correctly, considering the discrepancies in the results are clearly visible.
I don't even see how you would ensure consistency without rounding (which can be expensive), or somehow making sure you're only making divisions over whole binary values, since floating point operations produce an irreversible loss of information, which compounds.

See solutions like NTT.
vemusa
Burner Inserter
Burner Inserter
Posts: 13
Joined: Mon Jun 01, 2026 5:48 pm
Contact:

Re: Floating-point inaccuracies permeate the game.

Post by vemusa »

Rseding91 wrote: Fri Jun 26, 2026 10:03 pm ...these things don’t matter at scale...
I don't agree.
There is a thing called "productivity", and another thing called "circuit-controlled recipe". When these two things come together, inaccuracies matter.
Because productivity bar can also stuck at 99% when it should give a bonus craft.
In theory, this is the only chance to switch recipe without losing productivity.
But in practice, if productivity bar is stuck at 99% , switching recipe will lose the maximum possible amount of productivity.
Harkonnen
Former Staff
Former Staff
Posts: 235
Joined: Fri Sep 02, 2016 9:23 am
Contact:

Re: Floating-point inaccuracies permeate the game.

Post by Harkonnen »

Simple fixed point wouldn't help much either, what would - working on rational numbers in p/q format, both p and q being integers, but it may quickly overflow int64 unless everything is rescaled to sort of base-60 representation so instead of seconds time things are represented in ticks.
dupraz
Long Handed Inserter
Long Handed Inserter
Posts: 50
Joined: Fri Sep 01, 2023 6:45 pm
Contact:

Re: Floating-point inaccuracies permeate the game.

Post by dupraz »

Harkonnen wrote: Sat Jun 27, 2026 9:09 pm working on rational numbers in p/q format, both p and q being integers
This is exactly how "fixed-point" works. The library linked is a "48.16" implementation, meaning 48 bits for p (including 1 for parity), and 16 for q.
Harkonnen
Former Staff
Former Staff
Posts: 235
Joined: Fri Sep 02, 2016 9:23 am
Contact:

Re: Floating-point inaccuracies permeate the game.

Post by Harkonnen »

dupraz wrote: Sat Jun 27, 2026 9:57 pm
Harkonnen wrote: Sat Jun 27, 2026 9:09 pm working on rational numbers in p/q format, both p and q being integers
This is exactly how "fixed-point" works. The library linked is a "48.16" implementation, meaning 48 bits for p (including 1 for parity), and 16 for q.
I mean that initial values should map directly to that that kind of representation, but we have things like 0.1sec all over the place. Not only that 0.1 does not have finite base-2 representation, 1/60 of it wouldn't either both base-2 and base-10, so the only reasonable way to go is fixed point, but on ticks (1/60sec), and that's quite an overhaul for in how many places this is currently used. One way to go though while technically staying at floats is to resnap it back to 1/60 grid after every +-*/, e.g. v = floor(v*60е8+0.5)/60e8

P.S: Etymologically the word "second" comes from "second minute", so Factorio ticks deserve their place in vocabulary as the "third" ;)
dupraz
Long Handed Inserter
Long Handed Inserter
Posts: 50
Joined: Fri Sep 01, 2023 6:45 pm
Contact:

Re: Floating-point inaccuracies permeate the game.

Post by dupraz »

Harkonnen wrote: Sun Jun 28, 2026 12:34 am One way to go though while technically staying at floats is to resnap it back to 1/60 grid after every +-*/, e.g. v = floor(v*60е8+0.5)/60e8
Again, this is exactly how the /= operator works, and what is effectively being used for quality effects already, which is stored as an integer at a fixed resolution, which is then divided "for display purposes", only issue is that the resolution it was fixed at before 2.1 was... 1/10, which was not even accurate for even the most basic calculations. No idea why this wasn't the default approach.

I can't stress enough that floating-points are wildly inadequate for the simple reason that the innacuracy in absolute terms increases at high values to the point it quickly skips entire whole values (up to over 2^31 for a single step), the entire point being to allow for a greater dynamic range (say 2^127 instead of 2^31 for 32-bit), not higher precision.

Factorio doesn't need to store values up to 2^1024 (FP-64), not even 2^64 in fact, so it can afford to simply use these extra digits for decimal places (say 5 or 6), or rely on symbolic, fixed-point representations like any CAS.

Of course, that doesn't solve issues where the "ratios" being calculated by the game are neither able to be represented by decimal nor binary numbers, like the current Heat exchangers (1/97, prime denominator, which is admitedly silly), but then again, whether the inaccuracy is down to 6 decimal places, or 31, in these edge cases, makes little difference.

See also
Hurkyl
Filter Inserter
Filter Inserter
Posts: 273
Joined: Mon Dec 02, 2024 10:54 am
Contact:

Re: Floating-point inaccuracies permeate the game.

Post by Hurkyl »

dupraz wrote: Sat Jun 27, 2026 9:57 pm
Harkonnen wrote: Sat Jun 27, 2026 9:09 pm working on rational numbers in p/q format, both p and q being integers
This is exactly how "fixed-point" works. The library linked is a "48.16" implementation, meaning 48 bits for p (including 1 for parity), and 16 for q.
You've misunderstood something.

48.16 means that when you write out numbers in binary notation, there are always 16 places to the right of the point and 48 places to the left of the point. (thus, the position of the point is "fixed")

That corresponds to q being hard-coded to the constant 65536 in the rational number format. (and p being a 64 bit integer)
dupraz
Long Handed Inserter
Long Handed Inserter
Posts: 50
Joined: Fri Sep 01, 2023 6:45 pm
Contact:

Re: Floating-point inaccuracies permeate the game.

Post by dupraz »

Hurkyl wrote: Sun Jun 28, 2026 8:34 am 48.16 means that when you write out numbers in binary notation, there are always 16 places to the right of the point and 48 places to the left of the point. (thus, the position of the point is "fixed")

That corresponds to q being hard-coded to the constant 65536 in the rational number format. (and p being a 64 bit integer)
My point being, it's functionally equivalent to the manual integer-divided-for-display approach, except more convenient and predictable. Also p cannot be 64-bits since p and q must fit within 64-bits in the first place.
The only real solution for non-decimal values would be a true rational type, or simply designing the game to avoid these awkward values, which is fairly easy considering how most effect calculations are multiplications based on decimal representations. Problem would be values like 1/3, see how quality purposefully avoids them by using the a fixed 0.3 scaling factor instead? They literally figured out the solution by themselves then dropped it. Same problem as the heat exchanger design, once someone figured out how to do things that made sense, but then someone else did something completely differently, which results in these incomprehensible inconsistencies across the game. A general solution would be, obviously, to use a greater base-system which is a multiple of every base functionally necessary, 60 was mentioned, since it's a multiple of 2, 3, 10, etc. (30 would work just as well) but base 97 (which is currently used for Heat exchangers) would just not be acceptable unless you use rational types or something like base 223_092_870.

Going back to my simple burner miner example, here, progress is made by steps equal to 150/60, which is 2.5 J per tick, which should be able to be represented both with binary and decimal, even if it's floating-point instead of fixed-point, so what is going on here?
Last edited by dupraz on Sun Jun 28, 2026 9:38 pm, edited 1 time in total.
Panzerknacker
Filter Inserter
Filter Inserter
Posts: 377
Joined: Mon Aug 22, 2022 5:27 am
Contact:

Re: Floating-point inaccuracies permeate the game.

Post by Panzerknacker »

I think u newbz should show some respect to the devs which made the game like this probably for a good reason. If u don't like it play another game. They aint gonna change fundamental stuff like this at this point.
dupraz
Long Handed Inserter
Long Handed Inserter
Posts: 50
Joined: Fri Sep 01, 2023 6:45 pm
Contact:

Re: Floating-point inaccuracies permeate the game.

Post by dupraz »

Panzerknacker wrote: Sun Jun 28, 2026 9:37 pm the devs which made the game like this probably for a good reason.
There really isn't, using floating-points is not faster, and is simply less accurate, they probably defaulted to this without thinking much about it, then realized the problem by themselves while designing quality, changed the approach mid-way, and now the game has 2 conflicting approaches running concurrently (also known as an internal contradiction), one is accurate but (artificially) limited, the other is innacurate. It's fair to say the "performance hit" of using even full-blown rational types for every calculation would not be so significant since it only needs to be made when entity properties are being modified, not every tick (which can be cached, and probably already is).
Hurkyl
Filter Inserter
Filter Inserter
Posts: 273
Joined: Mon Dec 02, 2024 10:54 am
Contact:

Re: Floating-point inaccuracies permeate the game.

Post by Hurkyl »

dupraz wrote: Sun Jun 28, 2026 9:09 pm
Hurkyl wrote: Sun Jun 28, 2026 8:34 am 48.16 means that when you write out numbers in binary notation, there are always 16 places to the right of the point and 48 places to the left of the point. (thus, the position of the point is "fixed")

That corresponds to q being hard-coded to the constant 65536 in the rational number format. (and p being a 64 bit integer)
My point being, it's functionally equivalent to the manual integer-divided-for-display approach, except more convenient and predictable. Also p cannot be 64-bits since p and q must fit within 64-bits in the first place.
q requires zero bits of storage; it's hard-coded.

That's the point of a fixed-point data type: it's functionally identical to floating-point representations, but you don't have to use any bits to store the exponent part because you fix it to a constant (in this case to -16) and never change it. So you get a 64 bit significand rather than the 53 bit significand of the standard 64-bit floating point type which is great if you're in the range where you have enough precision and aren't wasting too much. (and the fixed exponent helps if you have to do a software implementation using integer types)

A general solution would be, obviously, to use a greater base-system which is a multiple of every base functionally necessary, you mentioned 60, since it's a multiple of 2, 3, 10, etc. (30 would work just as well) but base 97 (which is currently used for Heat exchangers) would just not be acceptable unless you use rational types or something like base 223_092_870.
You're missing the point that there are other, relatively arbitrary multipliers on things like power usage. For example, brownouts can throttle energy usage by an amount depending on the available and required power. Modules can change the energy usage too, which can again be fairly arbitrarily scaled if the beacon they're in is partially powered.

Going back to my simple burner miner example, here, progress is made by steps equal to 150/60, which is 2.5 J per tick, which should be able to be represented both with binary and decimal, so what is going on here?
I'm betting that there's an off-by-one error in expectations. Like, if you turn it on at tick zero, your burner miner outputs a coal at tick 240, 480, 720, and so forth.

Then if you supply the burner miner with exactly 600 kJ of energy, it will power the miner through ticks 0-239, and when tick 240 comes there is no fuel left, so the miner doesn't output its item because it's unpowered.
Post Reply

Return to “Outdated/Not implemented”