Strange behavior dividing number by itself, converting to integer

dequalsrxt's icon

I discovered this playing around with the modulo object, building a patch that makes a list of numbers that divide into another number without remainder. I happened to divide 107 by itself, which fed into [modulo 1.], and, instead of returning 0. as you would expect and as it does for (almost!) every other number, it returns 1. Weird. So I tried it the long way - divide and output a float, divide again and convert to int, subract int from float, get the remainder. But when I divide 107 by itself, with the div object set up to work with floats, instead of returning 1., it returns 0. Super weird. As I was building an example patch to share, I discovered there are other numbers that give the same results. Mostly primes, but not every prime and not exclusively primes. For example, 49 produces the behavior. As does any multiple of a number that produces the behavior. However, if I do the same calculations in gen, everything works as expected. I assume there's some floating point gremlins in there?

Max Patch
Copy patch and select New From Clipboard in Max.

Roman Thilenius's icon

i am isolating the "problem" a bit...

the floating point arithmetics itself is not the issue, 107./107. should give you 1. just as 105./105. does. there should to my understanding no floating point error arise at this point, no matter how huge the "int" is.

the issue seems to lie (sic!) more in the typecasting algorithm of [trigger] (and possibly most other objects) because such typecasting usually truncates down, and it is pretty sure that you can not truncate down 1.0-something to 0

[printit] (if we want to trust it for now) shows very well that that [number] and [/] do what you would expect from 32 bit or 64 float: 107.0/107.0 == 1.0; int(107.0/107.0) == 1

but the typecasting of the following object seems to think that the result is smaller than 1.0

in the above answer i assume that [printit] also correctly interprets what i gets, (which should be 0011111111110000000000000000000000000000000000000000000000000000)
if this is not the case, then it could indeed be a floating point error in max. (well, or a misunderstanding how it works. but then printit is a liar)

let's see what expr does, which probably uses overflow....

uh oh :)


Roman Thilenius's icon

evidence that 107./107. (single/double float) & using regular max objects, is not >= 1.0 (real number):

so... round-to-int or using expr (even in 64bit max, where expr is not using a higher resolution compared to the runtime, but still calculates differently from [/]), are two solutions to your problem.

dequalsrxt's icon

there should to my understanding no floating point error arise at this point

Yeah that's why I suspected gremlins, but your explanation is possible too I guess. Weird that it only happens with certain numbers.

so... round-to-int or using expr... are two solutions to your problem.

Or gen. Not sure why I didn't think to try expr, guess it was getting late when I discovered the behavior.

Roman Thilenius's icon

i went the long path because i can absolutely follow the confusion with things like that and felt it would be fun to elaborate verbosely on this.

in the end it is as simple as you suspected, it is an unavoidable float problem.
just not one with the float precision itself, but one with the way how most math objects work. (well, at least those which involve division... or actually.... multiplication....)
and as we see, on top of that not even mister printit can print a double as it actually is, and there is nothing in max which would allow you to see the binary or hex representation of a flaot, so literally everywhere you look you are beeing told by max that the result would be 1.000000.... while in fact it is 0.99999....

so always round to int before type casting and you are done. no need to become an expert in maths. i will never be one either.

dequalsrxt's icon

Appreciate the investigation. No worries about becoming an expert in math(s), I can barely do arithmetic.