Remainder(n, d) Better than MOD, same as capping wrapping?
#1
Break this? 
For ideal modulus, I imagine it should be between 0 and the divisor = modulus whether divisor is pos or negative.

I read johannhowitzer Wrapping, capping and other... and it all fell in place what we are trying to reach, keeping numbers between 0 and the divisor whether integer or float like Pi, we just want a proper remainder.

Code: (Select All)
_Title "Remainder test" ' b+ for a modulus that always returns a number between 0 and divisor
' if divisor is negative then return a rational between 0 and some rational d < 0
' if divisor is positive then return a rational between 0 and some rational d > 0
' if divisor is 0 ? can't divide by 0
' Do we need to round? Doesn't look like it but I just ran a couple quick tests. Folks here can find fault with anything! ;-))

' NOTE: when testing don't leave space between , and d  eg, do 5,3 not 5, 3

$Console:Only
Do
    Input "0's quit, please enter n, d to find remainder n/d between 0 and d "; n, d
    If (n = 0) Or (d = 0) Then End
    Print Remainder##(n, d)
    Print
Loop

' modeled on MODn
'ref Pete  https://staging.qb64phoenix.com/showthread.php?tid=1195&pid=10983#pid10983
Function Remainder## (n##, d##)
    If d## = 0 Then Exit Function
    Remainder## = n## - (d##) * Int(n## / (d##))
End Function

BTW best toggle I've seen and used often from Chia Pet:
toggle = 1 - toggle
b = b + ...
Reply
#2
@bplus

I responded to the formula Chris posted, in that thread, with a modification for negative mods...


Code: (Select All)
_Title "Remainder test" ' b+ for a modulus that always returns a number between 0 and divisor
' if divisor is negative then return a rational between 0 and some rational d < 0
' if divisor is positive then return a rational between 0 and some rational d > 0
' if divisor is 0 ? can't divide by 0
' Do we need to round? Doesn't look like it but I just ran a couple quick tests. Folks here can find fault with anything! ;-))

' NOTE: when testing don't leave space between , and d  eg, do 5,3 not 5, 3

$Console:Only
Do
    Input "0's quit, please enter n, d to find remainder n/d between 0 and d "; n, d
    If (n = 0) Or (d = 0) Then End
    Print Remainder##(n, d)
    Print
Loop

' modeled on MODn
'ref Pete  https://staging.qb64phoenix.com/showthread.php?tid=1195&pid=10983#pid10983

Function Remainder## (n##, d##)
    If d## = 0 Then Exit Function
    Remainder## = n## - ABS(d##) * Int(n## / ABS(d##))
End Function


So by putting ABS() in those two places your posted code will now handle negative modulo entries, like 7,-5 and -7,-5.

Pete
If eggs are brain food, Biden takes his scrambled.
Reply
#3
Pete, bplus is correct, there's no need for Abs
I posted basically the same in post #29 https://staging.qb64phoenix.com/showthre...3#pid10773
Reply
#4
Correct Jack, thanks.

My criteria for the return value is for it to be between 0 and the denominator, as stated right with the code.

This is a common requirement and not some wild idea I just came up with.

-5 into -7 leaves -2 remainder. Mainly the first post Remainder## keeps the numbers returned between 0 and the denominator.
b = b + ...
Reply
#5
Guys, I was going off of this: https://www.calculators.org/math/modulo.php

Amazing how much disagreement exists in so many of these math sites...

Pete
If eggs are brain food, Biden takes his scrambled.
Reply
#6
Yes, it could go either way I suppose. I see real use from me with keeping the return between 0 and denominator.
b = b + ...
Reply
#7
(12-04-2022, 01:38 AM)bplus Wrote: Yes, it could go either way I suppose. I see real use from me with keeping the return between 0 and denominator.

I've read it depends on the language how the results are represented. So without any reliable consistency, and a few different definitions, I'm in your boat. Use what is beneficial. To me a number MOD 5 should make a nice 1,2,3,4,5 pattern for file record recognition. In the second loop that is accomplished by setting the patented pattern variable to 1.

Code: (Select All)
$CONSOLE:ONLY
x = -5
pattern = 0
FOR y = -9 TO 10
    PRINT y; MODn(y, x, pattern)
NEXT
PRINT "==================="
pattern = 1
FOR y = -9 TO 10
    PRINT y; MODn(y, x, pattern)
NEXT

FUNCTION MODn (y, x, pattern)
    MODn = y - ABS(x) * INT(y / ABS(x)) + pattern * ABS(x) * (1 - ABS(SGN(y MOD x)))
END FUNCTION

Pete
Reply
#8
Barely remember that MOD operator thread that went a ridiculous number of posts, and something about it. This is something I have used many times programming in BASIC and in Lua. Where [n] is the dividend and when the answer requires [1,n] and not [0,n-1].

Code: (Select All)
FUNCTION modslide~&& (divi AS _UNSIGNED _INTEGER64, dsor AS _UNSIGNED _INTEGER64)
    'the following line should be to report an error in calculation:
    IF dsor = 0 THEN modslide = 0 : EXIT FUNCTION
    modslide = ((divi - 1) MOD dsor) + 1
END FUNCTION
Reply
#9
Why not just make 2 distinct mods which you can then call upon to get the output in whatever format you want?

Code: (Select All)
Print ModP(10, 3), 10 Mod 3, ModN(10, 3)
Print ModP(10, -3), 10 Mod -3, ModN(10, -3)
Print ModP(-10, 3), 10 Mod 3, ModN(-10, 3)
Print ModP(-10, -3), 10 Mod -3, ModN(-10, -3)
Print ModP(10, 3.14), 10 Mod 3.14, ModN(10, 3.14)
Print ModP(10, -3.14), 10 Mod -3.14, ModN(10, -3.14)
Print ModP(-10, 3.14), -10 Mod 3.14, ModN(-10, 3.14)
Print ModP(-10, -3.14), -10 Mod -3.14, ModN(-10, -3.14)



Function ModP## (num As _Float, div As _Float)
    Dim tempValue As _Float
    If div = 0 Then Error 5: Exit Function
    tempValue = num - Int(num / div) * div
    If tempValue < 0 Then tempValue = tempValue + Abs(div)
    ModP = tempValue
End Function

Function ModN## (num As _Float, div As _Float)
    Dim tempValue As _Float
    If div = 0 Then Error 5: Exit Function
    tempValue = num - Int(num / div) * div
    If tempValue > 0 Then tempValue = tempValue - Abs(div)
    ModN = tempValue
End Function
Reply
#10
(12-03-2022, 05:22 PM)bplus Wrote: Break this? 
For ideal modulus, I imagine it should be between 0 and the divisor = modulus whether divisor is pos or negative.

I read johannhowitzer Wrapping, capping and other... and it all fell in place what we are trying to reach, keeping numbers between 0 and the divisor whether integer or float like Pi, we just want a proper remainder.

Code: (Select All)
_Title "Remainder test" ' b+ for a modulus that always returns a number between 0 and divisor
' if divisor is negative then return a rational between 0 and some rational d < 0
' if divisor is positive then return a rational between 0 and some rational d > 0
' if divisor is 0 ? can't divide by 0
' Do we need to round? Doesn't look like it but I just ran a couple quick tests. Folks here can find fault with anything! ;-))

' NOTE: when testing don't leave space between , and d  eg, do 5,3 not 5, 3

$Console:Only
Do
    Input "0's quit, please enter n, d to find remainder n/d between 0 and d "; n, d
    If (n = 0) Or (d = 0) Then End
    Print Remainder##(n, d)
    Print
Loop

' modeled on MODn
'ref Pete  https://staging.qb64phoenix.com/showthread.php?tid=1195&pid=10983#pid10983
Function Remainder## (n##, d##)
    If d## = 0 Then Exit Function
    Remainder## = n## - (d##) * Int(n## / (d##))
End Function

BTW best toggle I've seen and used often from Chia Pet:
toggle = 1 - toggle
 I didn't see Chia Pet's post, but toggle = 1 - toggle always gives result=toggle; to toggle between 1 and 0 shouldn't it be toggle = Abs(toggle - 1) ?   
Of all the places on Earth, and all the planets in the Universe, I'd rather live here (Perth, W.A.) Big Grin
Reply




Users browsing this thread: 7 Guest(s)