Mod function returning wrong value?

Report problems with documented functionality
User avatar
jeeswg
Posts: 5742
Joined: 19 Dec 2016, 01:58
Location: UK

Mod function returning wrong value?

28 Mar 2017, 06:39

Code: Select all

q:: ;Mod issue? tested on AutoHotkeyU32.exe v1.1.25.01
MsgBox % Mod(12.345, 0.01) ;0.005000 (correct, as expected)
MsgBox % Mod(12.34, 0.01) ;0.010000 (bug?) (expected 0)
MsgBox % Mod(1.23, 0.01) ;0.010000 (bug?) (expected 0)
return
see: http://www.wolframalpha.com/input/?i=Mod(12.34,+0.01)
see: http://www.wolframalpha.com/input/?i=Mod(1.23,+0.01)

- Is this related to mathematics being done in hex/bin but rounded and displayed in dec?
- Should the documentation state a specific range in which Mod is correct?

Math Functions
https://autohotkey.com/docs/commands/Math.htm#Mod
Functions
https://autohotkey.com/docs/Functions.htm#Mod
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jNizM
Posts: 2352
Joined: 30 Sep 2013, 01:33
GitHub: jNizM
Contact:

Re: Mod function returning wrong value?

28 Mar 2017, 07:02

This one works...

Code: Select all

modulo(x, y)
{
    return x - ((x // y) * y)
}

MsgBox % modulo(12.345, 0.01)    ; -> 0.005000
MsgBox % modulo(12.34, 0.01)     ; -> 0.000000
MsgBox % modulo(1.23, 0.01)      ; -> 0.000000
[AHK] 1.1.30.01 x64 Unicode | [WIN] 10 Pro (Version 1803) x64 | [GitHub] Profile
Donations are appreciated if I could help you
User avatar
jeeswg
Posts: 5742
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Mod function returning wrong value?

28 Mar 2017, 07:48

Thanks. I came across this issue when looking at truncating/rounding numbers.

compare numbers with different decimal point - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 75#p138275

You've prompted me to write this function, where you can optionally choose whether the output is above/below zero.
[EDIT: ignore this function, see post lower down]

Code: Select all

;vMode: 1/0/-1, return pos/sign of dividend/neg
;note: assumes vDivisor is positive
JEE_Mod(vDividend, vDivisor, vMode=0)
{
	if (vDivisor = 0)
		return
	(vMode = 0) ? (vMode := vDividend) : ""
	vQuotient := Floor(vDividend / vDivisor)
	vRemainder := vDividend - (vQuotient * vDivisor)
	if (vRemainder < 0) && (vMode > 0)
		return vRemainder + vDivisor
	if (vRemainder > 0) && (vMode < 0)
		return vRemainder - vDivisor
	return vRemainder
}
I haven't made sense yet of what to do with a negative divisor.

Btw ooh, almost 2000 posts!
Last edited by jeeswg on 09 Apr 2017, 17:59, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jNizM
Posts: 2352
Joined: 30 Sep 2013, 01:33
GitHub: jNizM
Contact:

Re: Mod function returning wrong value?

28 Mar 2017, 08:36

qmath.h (AutoHotkey Source)

Code: Select all

#include <math.h>

// Inline assembly isn't available, so qmath is essentially disabled.

// ...
#define qmathFmod	fmod
// ...
The fmod functions compute the floating-point remainder of x/y and is not the same like the Euclidean division modulo.
fmod wrote:Returns the floating-point remainder of numer/denom (rounded towards zero):

fmod = numer - tquot * denom

Where tquot is the truncated (i.e., rounded towards zero) result of: numer/denom.

A similar function, remainder, returns the same but with the quotient rounded to the nearest integer (instead of truncated).
fmod, fmodf (msdn) - Calculates the floating-point remainder.

Code: Select all

MsgBox %         mod(12.345, 0.01)    ; -> 0.005000
       . "`n"   fmod(12.345, 0.01)    ; -> 0.005000
	   . "`n"  fmodf(12.345, 0.01)    ; -> 0.005001
	   . "`n" modulo(12.345, 0.01)    ; -> 0.005000

MsgBox %         mod(12.34, 0.01)     ; -> 0.010000
       . "`n"   fmod(12.34, 0.01)     ; -> 0.010000
	   . "`n"  fmodf(12.34, 0.01)     ; -> 0.010000
	   . "`n" modulo(12.34, 0.01)     ; -> 0.000000

MsgBox %         mod(1.23, 0.01)      ; -> 0.010000
       . "`n"   fmod(1.23, 0.01)      ; -> 0.010000
	   . "`n"  fmodf(1.23, 0.01)      ; -> 0.010000
	   . "`n" modulo(1.23, 0.01)      ; -> 0.000000

Code: Select all

modulo(x, y) {
    return x - ((x // y) * y)
}

fmod(x, y) {
    return DllCall("msvcrt\fmod", "double", x, "double", y, "cdecl double")
}

fmodf(x, y) {
    return DllCall("msvcrt\fmodf", "float", x, "float", y, "cdecl float")
}
[AHK] 1.1.30.01 x64 Unicode | [WIN] 10 Pro (Version 1803) x64 | [GitHub] Profile
Donations are appreciated if I could help you
User avatar
jeeswg
Posts: 5742
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Mod function returning wrong value?

28 Mar 2017, 10:17

Very good work jNizM, I'm most grateful.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 5742
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Mod function returning wrong value?

09 Apr 2017, 18:08

JEE_Mod(vDividend, vDivisor, vMode:=0) ;mimics AutoHotkey (result is same sign as dividend)
JEE_ModWA(vDividend, vDivisor, vMode:=0) ;mimics wolframalpha.com (result is same sign as divisor)

Code: Select all

q:: ;test Mod function and alternative Mod functions
vFunc := "Mod"
;vFunc := "JEE_Mod"
;vFunc := "JEE_ModWA"
vMode := 0
;vMode := 1
;vMode := -1

;e.g. http://www.wolframalpha.com/input/?i=Mod(7,-4)
;3 is the result with AutoHotkey
;-1 is the result with wolframalpha.com

MsgBox, % %vFunc%(7,4,vMode) ;3 (WA: 3)
MsgBox, % %vFunc%(7,-4,vMode) ;3 (WA: -1)
MsgBox, % %vFunc%(-7,4,vMode) ;-3 (WA: 1)
MsgBox, % %vFunc%(-7,-4,vMode) ;-3 (WA: -3)

MsgBox, % %vFunc%(7,5,vMode) ;2 (WA: 2)
MsgBox, % %vFunc%(7,-5,vMode) ;2 (WA: -3)
MsgBox, % %vFunc%(-7,5,vMode) ;-2 (WA: 3)
MsgBox, % %vFunc%(-7,-5,vMode) ;-2 (WA: -2)
return

;==================================================

;mimics AutoHotkey
;vMode: 1/0/-1, result is positive/same sign as dividend/negative
JEE_Mod(vDividend, vDivisor, vMode:=0)
{
	if (vDivisor = 0)
		return
	vDividendOrig := vDividend
	vDividend := Abs(vDividend)
	vDivisor := Abs(vDivisor)
	vQuotient := Floor(vDividend / vDivisor)
	vRemainder := vDividend - (vQuotient * vDivisor)
	if (vDividendOrig < 0)
		vRemainder *= -1
	if (vRemainder < 0) && (vMode > 0)
		return vRemainder + vDivisor
	if (vRemainder > 0) && (vMode < 0)
		return vRemainder - vDivisor
	return vRemainder
}

;==================================================

;mimics wolframalpha.com
;vMode: 1/0/-1, result is positive/same sign as divisor/negative
JEE_ModWA(vDividend, vDivisor, vMode:=0)
{
	if (vDivisor = 0)
		return
	vQuotient := Floor(vDividend / vDivisor)
	vRemainder := vDividend - (vQuotient * vDivisor)
	if (vRemainder < 0) && (vMode > 0)
		return vRemainder + Abs(vDivisor)
	if (vRemainder > 0) && (vMode < 0)
		return vRemainder - Abs(vDivisor)
	return vRemainder
}

;==================================================
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “Bug Reports”

Who is online

Users browsing this forum: No registered users and 4 guests