I'm looking for a simple explanation for how Ruby's modulo operand works and why, in Ruby
puts 4 % 3 # 1
puts -4 % 3 # 2 <--why?
puts -4 % -3 # -1
but in PHP:
<?php
echo 4 % 3; # 1
echo -4 % 3; # -1
echo -4 % -3; # -1
Looks to me like -4 % 3 is actally 8 % 3 (8 being the difference between 4 and -4).
They can both be considered correct, depending on your definition. If a % n == r, then it should hold that:
a == q*n + r
where q == a / n.
Whether r is positive or negative is determined by the value of q. So in your example, either of:
-4 == -1*3 + (-1) // PHP
-4 == -2*3 + 2 // Ruby
To put it another way, the definition of % depends on the definition of /.
See also the table here: http://en.wikipedia.org/wiki/Modulus_operator#Remainder_calculation_for_the_modulo_operation. You'll see that this varies substantially between various programming languages.
Here's a snippet on the topic from The Ruby Programming Language, by Matz and David Flanagan.
When one (but not both) of the operands is negative, Ruby performs the
integer division and modulo operations differently than languages like
C, C++, and Java do (but the same as the languages Python and Tcl).
Consider the quotient -7/3. Ruby rounds toward negative infinity and
returns -3. C and related languages round toward zero instead and
return -2. In Ruby, -a/b equals a/-b but my not equal -(a/b).
Ruby's definition of the module operation also differs from that of C
and Java. In Ruby, -7%3 is 2. In C and Java, the result is -1
instead. The magnitude of the result differs, because the quotient
differed. But the sign of the result differs, too. In Ruby, the sign
of the result is always the sign of the second operand. In C and
Java, the sign of the result is always the sign of the first operand.
(Ruby's remainder method behaves like the C modulo operator.)
It actually boils down to the implementation of the language's integer casting/rounding. Since the actual equation is:
a - (n * int(a/n))
It is the int(a/n) portion of the equation that differs. If a == -4 and n == 3, PHP will return -1, while Ruby will produce -2. Now the equation looks like this in Ruby:
-4 - (3 * -2)
and this in PHP
-4 - (3 * -1)
According to Wolfram Alpha, 2 is correct.
edit: Seems you should be asking why PHP works that way?
edit2: PHP defines it as the remainder from the devision A/B. Whether you consider it a bug, wrong, or a different way of doing things is up to you, I suppose. Personally, I go for the first 2.
Related
Looking at some code written by another developer, I came across this:
for($i=1; $i<=30; $i++)
{
if($i&1)
$color = '#fff';
else
$color = '#bbb';
}
This $color variable is used for row background colour later in the code. The alternating colours work fine.
If I was writing this, I would have used the modulus operator (%) rather than the bitwise (&) operator.
Why does the bitwise operator work in this case? Is there any advantage of using this method rather than the modulus operator?
The & operator does a bitwise comparison on the number. So if you do
$i & 1
it will then tell you if the '1' flag is set, such as in binary:
001010111010
The last number is the '1' flag (remember, binary goes 1, 2, 4, 8 etc. in reverse order), which in this case is set to 0.
Since 1 is the only odd flag in binary, it will tell you if the number is odd or even.
if $i is 3 for example, then in binary it will be 011 - the last number is a 1 (the 1 flag) and thus $i & 1 will be true.
if $i is 4 for example, then in binary it will be 100 - the last number is a 0 (the 1 flag) and thus $i & 1 will be false.
It works because the first bit is always 1 if the number is odd and 0 if the number is even.
1
10
11
100
101
110
111
etc.
In theory bitwise operation is faster than the modulus operation, but it's possible that the interpreter would have optimized the modulus operation down to bitwise operation anyway.
Why the other developer used it, we can only guess: out of habit, copy-pasted from somewhere, doesn't know about the modulus operator, showing off, wanting to optimize...
I have 5 different values which are saved as bits like 10010.
I get the value as an Int from the Database (cannot change that) so like 24 means 11000
I know that i can get the biggest bit here by using
if ((decbin($d) & 16) == 16)
but if the first is 0 i would have to check the next bit, and if that is 0 i would have to ...
So after all i would have a block of ifs and if there were more bits the block was bigger.
Is there a simple way to just get the "id" (or value, would not matter) of the highest bit with a 1?
Yes. Compute the base 2 logarithm of the number and floor it:
$highbit = floor(log($d, 2));
If $highbit, for instance, is 5, it means that the 5th bit is the highest bit set to 1.
The highest bit set in an integer is equal to the integer base-2 logarithm of that integer.
While there exist many different implementations for doing that kind of thing in assembler and C and such, more or less efficiently, the probably easiest way to do it in PHP is to actually use logarithm.
The log() function surely is not the most efficient way of solving the problem, but seeing as you are in a script language, it probably won't be any slower (and quite possibly faster) than implementing one of the "better" algorithms in PHP with 2 dozen statements.
Thus:
$highestbit = (int)(log($value,2));
Interesting ... had to check for rounding-problems immediately and found none in the range of up to 1'000'000, though my test-code revealed problems for less native bases, like 3:
3^5 = 243 but floor(log(243, 3)) gives 4
def hibit(v):
""" uint v -> highest bit: 0101 -> 0100, 01xxxx -> 010000 """
# cf http://graphics.stanford.edu/~seander/bithacks.html
v |= v >> 1
v |= v >> 2
v |= v >> 4
v |= v >> 8
v |= v >> 16
return v ^ (v >> 1)
for v in range(0, 9+1) + range(2**31-1, 2**31+2):
print v, hibit(v)
Feeling pretty brain-dead right now. I can, of course, brute-force this, but I feel like there has to be a simple function to return this number. Concerning native functions, I'm using PHP and/or Python.
For example: there exists containers that hold X (5) breadsticks each, and
I need to feed Y (25) people Z (3) breadsticks each.
I need to return the number of containers I have to acquire to feed these people. (There may or may not be remainder breadsticks).
EDIT: Clarified some intention.
It sounds like you want arithmetic:
min_containers = y*z/x
If you have situations that may give a remainder:
min_full_containers = floor(y*z/x)
remaining_items = y*z%x
def f(X, Y, Z):
d, r = divmod(Y * Z, X)
return d + bool(r)
In Python, use // (integer floor division, introduced in Python 2.2) and force it to round up:
number_required = y * z
container_holds = x
reqd_containers = (number_required + container_holds - 1) // container_holds
or if you require the so-called "professional programmer" version instead of the explanatory version:
n=(y*z+(x-1))//x;
or if you are really afraid of carpal tunnel syndrome, chop the two redundant parentheses and the semicolon:
n=(y*z+x-1)//x
Note: this solution works on both Python 2 (where 10 / 3 -> 3) and Python 3 (where 10 / 3 -> 3.3333333333333335)
Other "solutions" not only use unnecessary function calls but also fail with large numbers:
# wrong in Python 3; works with Python 2.3 to 2.7
# int overflow with Pythons up to 2.2
>>> int((100000000000000000 + 2)/3)
33333333333333332 # last digit should be 4
# wrong with Python 2.3 onwards; int overflow with earlier versions
>>> import math
>>> int(math.ceil(float(100000000000000000) / 3))
33333333333333332L
#python
import math
int(math.ceil(float(Y) * Z / X))
Ned's answer is correct. It is also common to avoid the function call overhead to math.ceil() by doing the following:
minContainers = int((y*z+(x-1))/x);
($people * $breadSticksPerPerson) / $holders isn't correct?
EDIT: Sorry, misread your question, posted the correct solution in comments
Derived from this question : (Java) How does java do modulus calculations with negative numbers?
Anywhere to force PHP to return positive 51?
update
Looking for a configuration setting to fix, instead hard-guessing
Or other math function like bcmath?
updated
Not entire convinced by that java answer, as it does not take account of negative modulus
-13+(-64) =?
Anyway, the post you referenced already gave the correct answer:
$r = $x % $n;
if ($r < 0)
{
$r += abs($n);
}
Where $x = -13 and $n = 64.
If GMP is available, you can use gmp_mod
Calculates n modulo d. The result is always non-negative, the sign of d is ignored.
Example:
echo gmp_strval(gmp_mod('-13', '64')); // 51
Note that n and d have to be GMP number resources or numeric strings. Anything else won't work¹
echo gmp_strval(gmp_mod(-13, 64));
echo gmp_mod(-13, 64);
will both return -51 instead (which is a bug).
¹ running the above in this codepad, will produce 51 in all three cases. It won't do that on my development machine.
The modulo operation should find the remainder of division of a number by another. But strictly speaking in most mainstream programming languages the modulo operation malfunctions if dividend or/and divisor are negative. This includes PHP, Perl, Python, Java, C, C++, etc.
Why I say malfunction? Because according to mathematic definition, a remainder must be zero or positive.
The simple solution is to handle the case yourself:
if r < 0 then r = r + |divisor|;
|divisor| is the absolute value of divisor.
Another solution is to use a library (as #Gordon pointed). However I wouldn't use a library to handle a simple case like this.
I hate using if in this case when you can calculate it right away.
$r = ($x % $n + $n) % $n;
when $n is positive.
The PHP manual says that
The result of the modulus operator % has the same sign as the dividend — that is, the result of $a % $b will have the same sign as $a. For example
so this is not configurable. Use the options suggested in the question you linked to
I've run into a problem whilst converting some C code to PHP, specifically in the use of the right-shift operator.
edit: in the following examples, bit = 0;
Original C code:
p->param->outBits[bytePtr++] |= codeword >> (9 + bit);
PHP code:
$outBits[$bytePtr++] |= $codeword >> (9 + $bit);
If I start with codeword being 130728, in C I get the expected result of -1. In PHP I get 255. I understand this is something to do with arithmetic/logical shift differences, and the negative sign not being introduced as a result of the MSBs staying at zero.
Is there a "quick" way of doing the above in PHP that doesn't involve the shifting? eg via basic arithmetic or similar, that will give me the expected answer?
Your problem is that PHP doesn't have a type byte, it only has integer which usually is 32 bits (not 8), so if you really need negative value there (the bits are correct anyway, because unsigned 255 is the same as signed -1), then you should probably add the missing 24 ones or use arithmetics to restore the negative value (255 is -1, 254 is -2 and so on i.e. 256 - x = -x).