P: 14

24 mod 7 = 3
The mathematical modulo can't return a value less than 0 according to the professors at my University but the function in Visual Basic 6 does.
Is there a fast way around this problem?
 
Share this Question
Expert 5K+
P: 8,434

Sure  use the Abs() function to get the absolute value, either before or after using Mod().
 
P: 14

Did you mean abs(a mod b) or abs(a) mod b?
That would reverse it either way.
  Expert 5K+
P: 8,434

Did you mean abs(a mod b) or abs(a) mod b?
That would reverse it either way.
Yeah, that's what I meant by "before or after". As long as it produces the desired result, I don't see that it makes any difference which way you go.
  Expert 100+
P: 1,295

Yeah, that's what I meant by "before or after". As long as it produces the desired result, I don't see that it makes any difference which way you go.
it doesnt make a difference, but both are wrong
24 mod 7 is 4
because the multiple of 7 below 24 is 28, and 24 ( 28) is 4.
The right way to fix this is
if you want (A mod B) and A < 0 then
(A *mod* B) = B + (A MOD B)
so 4 = 7 + (24 MOD 7)
you can wrap all in ABS to make it will work if B < 0
so use abs( B  (A MOD B))
HTH
Note i used MOD for the VB function, and *mod* for the "real" mathematical function.
So for an even more general function, you should use  if A < 0 then

if B < 0 then C = abs(B (A MOD B))

if B >= 0 then C = B+ (A MOD B)

else

C = A MOD B

end if
I'll think latter if this can be reduced to a single line.
  Expert 100+
P: 1,295

24 mod 7 = 3
The mathematical modulo can't return a value less than 0 according to the professors at my University but the function in Visual Basic 6 does.
Is there a fast way around this problem?
What vb function does to get C = A mod B is
C = A  fix(A/B) * B
when the real definition should be
C = A  int(A/B) * B
The difference is that INT will give you the integer below a number, FIX will give you the integer part, e.g.
FIX(1.8) = 1
INT(1.8) = 2
I dont know why VB has the function that way, may be some people rather use it like that.
Anyway, instead of using MOD, you can use the definition i've just wrote
HTH
  Expert 5K+
P: 8,434

24 mod 7 is 4
Really? Mathematics does some weird things at times. 3 (or perhaps 3) seems much more logical.
I dont know why VB has the function that way, may be some people rather use it like that
I'd suggest two main possibilities...  The people who built VB didn't know it was supposed to work that way. I still say their way seems more intuitive, or at least logical.
 The Int() function is slightly faster. And perhaps they figured nobody would notice  after all, look how long it's taken. :)
Also, they may have spotted the mistake years ago, but couldn't change it without potentially upsetting too much existing code. Wait! What am I thinking  look who we're talking about.
As for the general function, I'd be interested to see whether we can crunch it down to a single line (though of course it's not necessary since it would probably be kept in a Public Function somewhere). My first guess is that the SGN() function might come be useful in this regard.
  Expert 5K+
P: 8,434

Here are two attempts at a singleline version of the corrected Mod() function. They're straight off the top of my head. I've checked that VB is happy with the syntax, but if either of them actually works that'll be a bonus.  Public Sub RealMod(A As Long, B As Long)

RealMod = Abs((B * Abs(A <> B)) + (A Mod B) * Sgn(B))

RealMod = Abs(IIf(A >= 0, A Mod B, IIf(B < 0, B  (A Mod B), B + (A Mod B))))

End Sub
To be strictly accurate, the above is not an attempt to produce a corrected Mod() function. It's an attempt to boil down to a single statement the code that Kadghar posted. Whether the two are in fact the same, I'll leave to the mathematicians out there. :)
 
P: 61

Try this :
24/7 = 3.4286;
Round down to nearest integer
= 3;
now find remainder,
7* 3 = 21
24  (21) = 3
Yup that is correct.
No it's not broken, it works perfectly.
That is it functions exactly the way the compiler implimented it.
Are the Engineers Broken?
Yes, The remainder r is supposed to be between zero and the divsor.
0 <= 3 < 7
  Expert 100+
P: 1,295

Try this :
24/7 = 3.4286;
Round down to nearest integer
= 3;
now find remainder,
7* 3 = 21
24  (21) = 3
Yup that is correct.
No it's not broken, it works perfectly
No, you dont have to round to the nearest integer, you have to use the immediate before integer.
check it here:
3 mod 5 = 2
well. its writen as a congruence relation.... But definitions really don't matter, it depends on what you need to do, and know what you are doing in your code and how you use it to achieve a result.
  Expert 5K+
P: 8,434

Have you tried my squashed code? I haven't had a chance yet.
 
P: 61

Think about it terms of distance on a chart
24 is 24 whole units from 0,
7 is 7 whole units from 0;
24 whole units can be split up into how many chunks of 7 whole units,
And how many remain?
24 % 7 = 3;
[quote]the expression a ≡ b (mod n) (pronounced "a is congruent to b modulo n") means that a − b is a multiple of n.[/qoute]
3 is congruent to 2 ( using modulo 5);
means that 3 minus 2 is an even multiple of 5, that is the distance between them is a multiple of 5.
And we can see that 3  2 = 5, and it is an even multiple of 5.
3 % 5 = 3, not 2
8 % 4 = 0, that is to say that
8 is congruent to zero (using modulo 4)
6 % 5 = 1;
6 is congruent to 1 (using modulo 5)
3 % 5 = 3;
8 % 5 = 3;
so 8 is congruent to 3 ( using modulo 5)
And actually (using modulo 5 ) there are 5 distinct sets of congruent numbers.
the compiler has defined the modulo operator to return the "Remainder" not the set of congruent numbers.
so again, for a distance of 24, the reamainder of division by 7 = 3
and since 3 is the distance from 0 to 3 you can safely say that
24 % 7 = 3;
Yup it works every time.
24 is congruent to 3 (using modulo 7), and consequently
24 is congruent to 4 ( using modulo 7)
So would you say 24 % 7 = 4?
No, becuase of the definition of the operator. The distance is from zero
even though 24  ( 4 ) = 28, we are looking for the remainder of deviding the distance from zero not from 4 therfore
24  ( 0 ) = 24,
and indeed the remainder of 24 / 7 is 3
 
P: 61

Try this :
24/7 = 3.4286;
Round down to nearest integer
= 3;
actually its 4, rounding down.
But we arn't talking about negative or positive #'s anymore, we are talking about direction.
and 3 = 3 They if you pardon the pun congruent.
No, you dont have to round to the nearest integer, you have to use the immediate before integer.
well. its writen as a congruence relation....
and indeed
4 * 7 = 28 ; 24  ( 28 ) = 4
So we see that 4 is congruent to 3 (using modulo 7)
But since 0<= 28 < 24 is false 4 cannot be the "remainder".
using 2 we find that 7*2 = 14 ; 24  (14) = 10
We see that 10 is congruent to 3 ( using modulo 7) but since
0 <= 10 < 7 is false; 10 cannot be the "remainder".
The Correct calculation is
24 % 7 = 3 == 24 % 7 = 3 ( in the negative direction)
I hope this helps.
  Expert 100+
P: 1,295

...
I hope this helps.
Sure it helps, and you do make a point: The vb modulo operator is right in deed. (but ABS won't help it, sorry this time Killer)
I thought it was like using a clock, like when you have 20hrs its 8pm, because 20 mod 12 is 8. Same if you have yesterda's 4pm is the same as having today's 8. I think it all depends on how you're using it in your code. e.g. in a countdown, i bet 8 will be more useful.
Anyway, if C is A mod B (where B >0):
VB will make C = A  fix(A/B) * B.
I think the problem is that many (including me, and i assume Dawoodoz's teacher too) would expect it to make C = A  int(A/B) * B (i.e. give you 4pm instead of 8)
But as long as you know what you're doing, and you use it to achieve the result you want in your code, i think a definitions discussion is not necesary.
  Expert 100+
P: 1,295

Have you tried my squashed code? I haven't had a chance yet.
Yes. I just changed it to be a function, and it works great. But i think if it comes to make a function, using the definition will be faster:  Public Function RealM(A As Long, B As Long) As Long

B = Abs(B) : RealM = A  Int(A / B) * B

End Function
^.^
  Expert 5K+
P: 8,434

If you want faster, you probably should use integer division (\) instead of regular (/). In which case, you might not need the parentheses (not sure).
Also, this function should use ByVal for the parameters, so that it doesn't change the variable passed to argument B. Alternatively, you could just define a local variable and use that in place of B.
(I think passing by value is the default in .Net versions, isn't it?)
  Expert 100+
P: 1,295

...
Also, this function should use ByVal for the parameters, ...
I missed it because of my "#$@"% copypaste habit. Of course it should be ByVal B as Long.
 
P: 14

Thanks for the replies. I have a lot to try now. XD
    Question stats  viewed: 6070
 replies: 17
 date asked: Feb 3 '08
