modulo object error?
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?
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).
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).
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 ;-)
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.
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:
-- Pasted Max Patch, click to expand. --Copy all of the following text. Then, in Max, select New From Clipboard.----------begin_max5_patcher---------- 512.3oc2VFsaaBCEF9Z3ovBocWZjMXmA6h8XralplLfShmfii.iZ5p569rMv JKMYjPRYU8Fr3.3y++24Xiex2KHUsWTGf9B56HOum787bgrA75t2KnjuOqfW 6dsfLUYo.zAKZelVrW6hmJLOQTiTf.8vVAfjvtFMRVi.AuBkpZfbd0i8e2Nt NaqD17iJQltM+rUzk3EnHRncHjtxMfWhQ228QqUfF3kBWB+lnJmC79ITl6hp R+4cQr9fPSoDJDZmzIuDT0n6ihGL20xe4laBYI1F8Yee6kEmIZzpMaJD84tM G5G2IZsWfzPs+Xki4eJdn+wux9CsXzEXQxD7BHdvjmWUk+JxHHZRRx05xv3X 6vpjIWjIGk.gGm.2th7I.COs1flSRk0EJ94wk1EAT1j4B9R5Ldy4xc1FF1Mf KsCT5T4R3m++zuXbnYtGA.KL6exgM+SPPiGt8.COUPPtjcGCeyaPzn0n0iim waT53SHt8uHgKYSjOQuq3ymLKfHSd21NnPhuxUOrOFKdHL2gJRhmJGn21dCW 5CJjvgmAyYAa7+FN0plprd22UWPuXhbQsVBbsTACdGaC8fWZqLOW.CO5SoLe mxzI0oAz8GsRctR5fzcBMwleMQFQS1+PLiZxd.lQ4Tz7V6rGdXbMQlUMcPY4 DZBOqZhdFR5Z5vM27r+uAb87j7L -----------end_max5_patcher-----------
A ha–I thought I searched the forums pretty well but apparently not. ;)
Thanks to both of you for helping me understand!
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. < ftp://arts.ucsc.edu/pub/ems/maxtutors/Max&Numbers.pdf>
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.
> 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
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 %.
what about doing the same with ints?
expr can only do integers modulo. This has been the case for ever.
i was confused a bit about the situation, you are right, %0.1 wont work.
there are two things which work:
you may input and output floats in an modulo expression, which
wasnt the case the [%] external in max 4, but works with expr.
and of course you can make your own modulo for floats – USING expression.
there is something wrong with my attachment
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 + ....
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.
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.
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].
Forums > MaxMSP