modulo object error?

Paul Turowski's icon

It seems that the modulo object in Max doesn't work correctly with floats. Maybe I'm missing something, but 0.5 % 0.1 yields 0.1 when it should yield a 0. (It works fine with float up to .5) Similarly, 1. % 0.2 outputs 0.2 when it should also be 0. Right?

Paul Turowski's icon

OK so in trying to figure out a work-around for this, I used a select object to detect when the output is 0.1 and bang a 0. instead. Except this doesn't work. Can anyone replicate this or have I simply gone mad?

1522.modtest.maxpat
Max Patch
Emmanuel Jourdan's icon

0.1 % 0.1? hum, that's 0, right? If you do a modulo something, you'll never reach the something value (cause the remainder of something/something is 0).

Paul Turowski's icon

Hi Emmanuel,

Yes that's right, and that's the result that I would like to get--0. However, I am getting 0.1 instead. :(

i.e. 0.5 % 0.1 should yield 0.0 because .5/.1=5 (no remainder).

Emmanuel Jourdan's icon

32 bits floating point. There's several thread which talks about that, but basically sel 0.1 is actually looking for the value 1.000001. 0.5/0.1 is about 0.99998 or something. So that's why select doesn't select ;-)

Paul Turowski's icon

Not sure that I understand how 0.5/0.1 is .99998 (or even .099998) but I'll take your word for it. Still, that was just a workaround for the modulo problem. It would be nice if the Max modulo object worked consistently (like a standard calculator) so I could use it practically.

jvkr's icon
Max Patch
Copy patch and select New From Clipboard in Max.

Consistently is not always as expected. Probably Emmanuel meant to say that 0.5/0.1 is about 4.99998 or something (and not 5). When you do a forum search, search for "float castine". These two concepts are eternally connected. In the meantime, you could solve your problem like this:

_
johan

Paul Turowski's icon

A ha--I thought I searched the forums pretty well but apparently not. ;)

Thanks to both of you for helping me understand!

Peter Castine's icon

I was about to reply and then saw that it would be irrelevant. Thanks for the compliment (I think), Johan!

There is, of course, the tutorial written by another Peter (Elsea). Highly recommended.

Roman Thilenius's icon

i tend to trust people like emmanuel, but i dont understand what he says.

why cant you do a modulo for floats? i do that sometimes.

because i am in mac os classic most of the time, i have to use [expr], of course, and
it does not happen too often that i need to do it, but it "works".
(who cares that math books usually claim the opposite?)

pauls example seems absolutely valid to me:
"i.e. 0.5 % 0.1 should yield 0.0 because .5/.1=5 (no remainder)"

and [expr $f1%$f2] should output 0 when i am not wrong.

-110

jvkr's icon

> and [expr $f1%$f2] should output 0 when i am not wrong.

PPC might be able to do that; Intel apparently not. It crashes max--the one with rounded corners. (10.6.5 / 5.1.7)

Thread 0 Crashed: Dispatch queue: com.apple.main-thread
0 com.cycling74.MaxMSP     0x00034b94 ex_eval + 2240
1 com.cycling74.MaxMSP     0x000386aa expr_bang(expr*) + 32
2 com.cycling74.MaxMSP     0x000655f0 outlet_float + 776
3 com.cycling74.MaxAPI     0x0327154b outlet_float + 54
4 com.cycling74.number     0x1935ca1f jflonum_mousedragdelta + 342
5 com.cycling74.MaxMSP     0x000bb49b object_method + 901
6 com.cycling74.MaxMSP     0x0010ca73 BoxComponent::mouseDrag(juce::MouseEvent const&) + 439
7 com.cycling74.MaxMSP     0x002f5bac juce::Component::internalMouseDrag(int, int, long long) + 646
8 com.cycling74.MaxMSP     0x0038fc26 juce::ComponentPeer::handleMouseDrag(int, int, long long) + 114
9 com.cycling74.MaxMSP     0x002d2ad2 juce::juce_dispatchNextMessageOnSystemQueue(bool, bool) + 294
10 com.cycling74.MaxMSP     0x002dc87f juce::MessageManager::dispatchNextMessage(bool, bool*, bool) + 79
11 com.cycling74.MaxMSP     0x002dc93e juce::MessageManager::runDispatchLoop() + 42
12 com.cycling74.MaxMSP     0x002db299 juce::JUCEApplication::main(juce::String&, juce::JUCEApplication*) + 605
13 com.cycling74.MaxMSP     0x002db373 juce::JUCEApplication::main(int, char**, juce::JUCEApplication*) + 125
14 com.cycling74.MaxMSP     0x001e4b00 main + 76
15 com.cycling74.MaxMSP     0x0000647a _start + 216
16 com.cycling74.MaxMSP     0x000063a1 start + 41

Roman Thilenius's icon

oh, so there is actually an appearance of an expr which does not work on a platform.

well, i know why i didnt like the rounded conders, they can not even do %.

Roman Thilenius's icon

what about doing the same with ints?

Emmanuel Jourdan's icon

expr can only do integers modulo. This has been the case for ever.

Roman Thilenius's icon

i was confused a bit about the situation, you are right, %0.1 wont work.

there are two things which work:

1.
you may input and output floats in an modulo expression, which
wasnt the case the [%] external in max 4, but works with expr.

2.
and of course you can make your own modulo for floats - USING expression.

-110

1524.modulofloat.jpg
jpg
Roman Thilenius's icon

there is something wrong with my attachment

Peter Castine's icon

i.e. 0.5 % 0.1 should yield 0.0 because .5/.1=5 (no remainder)

Sigh, it looks like Castine does have to explain this yet again.

The value 0.1 simply does not exist in binary fractions.

It's just like trying to express 1/3 with decimal fractions. You can approximate 1/3 as 0.33 or 0.333 or 0.33333333333333333333333 but you can never express 1/3 *exactly*. Not unless you have time to write an infinite number of digits. Most computers have neither infinite amounts of time nor memory.

With binary fractions you can only express any fractional value as the sum of 1/2, 1/4, 1/8, 1/16 and so on. So the closest you can come to 1/10 is:

1/16 + 1/32 + 1/256 + 1/512 + 1/4096 + 1/8192 + ....

Or: 0.00011001100110011001100110011....

The net result is that the 32-bit floating point representation of 1/10 is actually 0.10000011324882507 (after rounding).

Pretty close, inn't? It even looks absolutely correct after rounding to less than six digits. But it ain't.

So, guess what happens when you try to take 0.5 (which *can* be represented exactly in binary) modulo 0.10000011324882507? The division of 0.5 by 0.10000011324882507 gives a quotient of 4 and a remainder of something like 0.099999547, and the later is displayed as 0.1

Working out the arithmetic with 18-digit decimal precision is left as an exercise for the reader.

Peter Castine's icon

PS: one solution is to stick to the integer domain as long as possible. Instead of doing [% 0.1], multiply your input by 100 (with rounding if appropriate) and do a [% 10], then divide the output by 100.0 when you've finished processing.

Roman Thilenius's icon

where is peter when you need him.

ah, there he is.

as long as we are talking about %0.1 or %0.01 the chance to get a wrong result is exactly 0, isnt it?

the problem you describe only appears with fractions with periods, which i believe
noone would use with %, 0.33333334 just doesnt look integer enough even to the noob.

you only explained why the % object doesnt take float arguments, but i see no reason why
he should do *100 when you need %0.01.
of which we could argue if it exsists at all - but obviously you can get a result from using it.

as you stated yourself [expr 1.0 / 3.0] will also give you wrong results (from the perspective of
an int-thinker) so why bother about % 0.01?

furthermore, where is the excuse for [expr $f1%0.1] chrashing intel but not PPC?

i would exspect an "error: wrong expression" or something like that, like when you
attempt to calculate [expr log($f1,300)] or [expr bang>0].

-110