expr for non-rational decimals?

brendan mccloskey's icon

Hallo all
I wish to remap linear decimal/fractional input (between 0.0 and c. 40.0), how can I avoid 'rounded' output values? I would like to avoid 0.1, 0.125, 0.25, 0.5 etc. As a quick fix I just did: * 0.017, which seems to work, subjectively at least. Ideally my output (integer or float) would only ever end in a 2, 3, 4, 6, 7 ,8 or 9. Might a solution involve prime numbers or pi?

Thanks
Brendan

Roman Thilenius's icon

maybe i missed something, but why not scale-then-round-to-int?

expr ((scalestuff)>=0) * (int((scalestuff)+0.5)) + ((scalestuff)>0) * (int((scalestuff)+0.5))

brendan mccloskey's icon

Hi Roman
I'm not sure I grasp this solution. What I am hoping to do is generate rational decimals that do not end in 2, 5 or 0, given input between, say, zero and 40, but the upper limit could depend upon the scaling expression. By "scalestuff" do you mean input values?

It's a control mapping inside a quantized modulator FM engine, and whenever I set the 'trigger rate" parameter to a value of 1.0, 0.25, 0.125, 0.5 etc, the oscillator outputs a static value, which I would like to avoid. But doing trig = trig* 0.137 seems to work ok. Because that only outputs a decimal ending in 5 once, and it's a very small value so it's negligible.

Roman Thilenius's icon

sorry, with "scalestuff" i meant "yourexpressionhere", i.e. scale as usual, round to int. (it doesnt matter, my expr was wrong anyway.)

but i think versions of expr later than mine will just allow you to use round()

it could be that for your approach it will actually be best to either somehow start from 1/primes or add 0.017 to all output vallues, because checking an arbitrary result against all possible integer rational numbers might end up in a neverending iteration. (if you dont want any n*1/2 to n*1/512 thats a lot of numbers!)

brendan mccloskey's icon

Thanks Roman. I'll try your suggestions.

Roman Thilenius's icon

when i think about it (which i just did), you can probably not avoid checking the float result against beeing 1/int or not, but you can of course do it in one easy formula:

[expr ((1./$f1)!=(int(1./$f1)))*$f1]

followed by [route 0] this will now filter out all appearances of 1/int. (e.g. 0.125 and friends)

now you could go further and filter out a range of 0,001 or of 0,3% of the value around 1/int or whatever you want to avoid. (if you take a DX7 as example, it uses values such as 1.03 or 2.97 for the ops)

Rick's icon

You could use sprintf to decide how far you want the decimal place to go and add any of your non-static numbers to the end.

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

brendan mccloskey's icon