route int / float question

schlam's icon

Hello.
I need to know if a float number "is an integer"..

If I send "32" and "32.2" to [route int float]
it's working good to know what number is a float or an integer.

Here I need to route "32.0" to be recognize "as an integer"
but all other 32.xxxx has still to be routed to float

schlam's icon

For information, I need that because I am looking for a way to know if a number is or not a multiple of, for example 3.
But maybe there is a more clever solution..
For now , I divide the number by 3 and try to route the solution between integer and float...
If it's integer it's a multiple of 3, if it's a float, it is not..

any idea ?

thank you !

yaniki's icon

A solution for this class of problems may be implemented in Max in several ways. This is something I prefere:

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

About this example: because of the nature of the mechanisms behind floating point arithmetic a direct comparison is not a good idea. Better to assume that the decimal part less than the threshold means that the number is an integer.

schlam's icon

it's perfect !
thank you Yaniki !

Roman Thilenius's icon


atchoo.

shhht: expr ($f1-int($f1)) == 0.

schlam's icon
yaniki's icon

@Roman

I think this should work correctly, however direct comparison (of two floating point values) is often treated as a bad practice: https://bitbashing.io/comparing-floats.html

Anyway it should work, of course ;-)

Roman Thilenius's icon


it works great until 0,00001, just not for smaller numbers.^^

of course my suggestion is only a compromise, too. while 0 int and 0 float are actually no problem, the float to int conversion of the int() operator is.

i am a bit biased here because i use 32 bit max, and in 32 bit there is no real danger to use $f1 besides of int($f1), because both are converted to a 64 bit float value inside expr. and you can be sure that it is the same value.

... i think. :D

Roman Thilenius's icon


what i mean is, mine might also be not perfect for up to an exponent of -380, but it will be perfect for the number precision you can and want to type into objects usually.

the int() operation already brings you to the float value with the smallest possible difference to ints - and in the case of 0 and 0. they are even identical.
so checking for is not zero should be sufficient, except maybe for the smallest possible 64 bit value (i am too dumb to test that within max)

yaniki's icon

Yes, of course. This is a "weakness point" of this solution (but you can just make the threshold smaller if you want to). However the "power point" is avoiding direct comparison, which may be problematic in case of floating point numbers. The most classic and reliable algorithm to compare floats for equality/inequality is by taking the absolute value of their difference and comparing it to a small enough (so called epsilon method).

I don't know if floatA == floatB in Max is epsilon-based. From my experience it is, but it is not explicitly declared, so to cut eventual problems it will be good to make a safe code.

yaniki's icon

Haha... this is really interesting conversation!

yaniki's icon

> i am a bit biased here because i use 32 bit max, and in 32 bit there is no real danger to use $f1 besides of int($f1)

64bit Max seems to be epsilon-proof too. I tried to force floating-point-comparison-error with no success (well... no error). Very interesting.

Roman Thilenius's icon


i believe the contradiction lies in the attempt to to "compare" float and int values already (i.e. in the OPs question), and not in the comparison between (int(float)) and (float).

(did you notice? you answered his question by writing "int" and "float" beside your result - but of course that is not what the patch is doing.)

and while you could lower the value to cover more use cases, it will require quite a lot of screenspace then, which the question after zero or nonzero does not.

yours is longer. is that bad or good?


Roman Thilenius's icon


more interesting, but not the case here, would be the question how to compare 3 against 3.* , without substracting them from each other, that is.

then we would have to find out if the incoming float is the closest possible float to 3 int. probably not a good idea to implement that using arithmetics, more a bitwise operations job.

yaniki's icon

Fixed threshold (epsilon) value is, even if I used it, also not a good practice, as this "error margin" should be calculated (or be accessible via some kind of interface) in accordance to formats of values we want to compare.

It's not precisely my field of interest, but, as far as I know, most of algorithms for int-float or float-float comparison are tailored for a specific applications and not to be a universal solutions.

schlam's icon

I am happy to see that my "noob question" generates a so interesting conversation ;)
In my case all your solutions are working good. Thank you all to open my mind :)

In this case, I am looking for a way to know if a number is a multiple of 3, is it the more efficient way to divide it by 3 and after to route the results with your solutions ? I dont think of another ways. They are ?

Nick Holmes's icon

then we would have to find out if the incoming float is the closest possible float to 3 int.

The closest possible float value to any integer is always an integer!

Source Audio's icon

I would do this

you don't need that many decimal places , I guess

yaniki's icon

I prefer the solution which I posted on beginning on the topic, but technically-simplest-within-max option is probably something like that (however I don't like this solution for the reasons set out above):

Roman Thilenius's icon


"The closest possible float value to any integer is always an integer!"

well, if this was true, the problem would not exist.

987654321987654321 is stored as 110110110100110110100101111101111110111101000001001010110001, which represents 987654321987654321, but in float64 it is stored "with only 53 bits of precision" as 01000011 10101011 011010011011010010111110111111011110100000100101, which converts back to 9.87654321987654272E17.

if you attempt to compare these values, it will return false.

not to speak of the other issue, which is that you never know what a program/language actually does when converting between types, as far as i know there is not "wrong" and "right" for that.


Nick Holmes's icon

9.87654321987654272E17 is an integer, so it doesn't disprove what I said: "The closest possible float value to any integer is always an integer!

Roman Thilenius's icon


>99,99% of all possible integers dont survive the conversion to float without errors, because in float the precision is lower.

that you get another integer value after doing int() is not so useful for comparing them.