It's not really related, but that reminds me of how some games handled slow moving objects on the Mattel Intellivision console.
Your code that runs every frame to update the graphics logically wants to do something like this:
X += Vx
Y += Vy
where (X, Y) is the location of the object at the start of the frame, and (Vx, Vy) is x and y velocities of the object in pixels/frame.
To allow for velocities that aren't an integer number of pixels per frame and that are slower than 1 pixel per frame you'd want to actually store X in a fixed point format, say (Xi, Xf) where Xi is the integer part of the X position, and Xf is the fractional part times 256, so X = Xi + Xf/256. Similarly for Y. The object only actually moves on the screen when Xi or Yi changes.
Similarly velocity would also be in that format: Vx = Vxi + Vxf/256, and similar for Vy.
With that, the position update in your loop would be something like this:
Xf += Vxf
if that wrapped
Xi += 1
Xi += Vxi
and similar for Y.
For each object you end up needing 8 bytes (1 byte for each of Xi, Xf, Yi, Yf, Vxi, Vxf, Vyi, Vyf). That doesn't sound like much but the Intellivision only had something like 240 bytes in the console available. (If you couldn't get your RAM requirements down to that it was possible to have extra RAM in the cartridge but that would raise the cost).
So someone figured out that you didn't actually need to store Xf and Yf. Just generate then at random as needed! The loop then becomes something like this:
rb = random_unsigned_byte()
if Vxf + rb wraps
Xi += 1
Xi += Vxi
and similar for Y.
That turns out to work quite reasonably. Essentially it is interpreting Vxf as meaning that the object has a Vxf/256 chance of crossing a pixel boundary on a given frame. Thinking of it that way then suggests getting rid of the addition of the random byte with a wrap check and just doing a compare instead:
if Vxf > random_unsigned_byte()
Xi += 1
Xi += Vxi
and similar for Y.
Net result: we've cut the RAM for storing position and velocity from 8 bytes per object to 6, at the cost of needing to generate 2 random bytes per object per frame.