Forums > MaxMSP

modulo object error?

December 10, 2010 | 10:05 am

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?


December 10, 2010 | 10:25 am

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?

Attachments:
  1. modtest.maxpat

December 10, 2010 | 10:50 am

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).


December 10, 2010 | 11:18 am

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).


December 10, 2010 | 12:01 pm

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 ;-)


December 10, 2010 | 1:31 pm

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.


December 10, 2010 | 1:58 pm

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. –

_
johan


December 10, 2010 | 2:04 pm

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

Thanks to both of you for helping me understand!


December 10, 2010 | 2:06 pm

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>


December 10, 2010 | 2:29 pm

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


December 10, 2010 | 3:06 pm

> 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


December 10, 2010 | 3:37 pm

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 %.


December 10, 2010 | 3:38 pm

what about doing the same with ints?


December 10, 2010 | 4:26 pm

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


December 11, 2010 | 8:04 am

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

Attachments:
  1. modulofloat.jpg

December 11, 2010 | 8:05 am

there is something wrong with my attachment


December 11, 2010 | 6:42 pm

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.


December 11, 2010 | 6:49 pm

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.


December 12, 2010 | 6:57 am

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


Viewing 19 posts - 1 through 19 (of 19 total)