I confess I don't really know what I'm doing! I'm pulling some data from SecondLife and parsing it in PHP. The data is an integer from llGetRegionFlags which, in my case, returns 1048592
Now I need to do a bitwise comparison in PHP to figure out which flags are true/false. For example 0x00000040 is used for the "block terraform" flag.
The notations are in hex for each flag, and I have an integer to test against, and the PHP manual suggests integers and shows examples in binary.
So my question really is, given an integer and some hex flags, how do I go about doing the bitwise comparison in PHP? Brainfried! Thanks in advance
To determine if a particular bit is turned on, use the & (AND) operator:
if ($data & 0x00000040) {
// block terraform flag is true
}
If the bit is turned on, the AND operator will return a positive number. If it is turned off, then the AND operator will result in a zero.
Use a single AND & / OR |
if ($value1 & $value2) { }
The PHP Manual explains more: http://php.net/manual/en/language.operators.bitwise.php
You could define the bits required, and check against them to make it look clean. ie
define('BLOCK_TERAFORM', 0x00000040);
....
if($data & BLOCK_TERAFORM) {
... do something ...
}
Usually the bitflags are checked with a piece of code like this:
$blockTerraformFlag = 0x00000040;
$isBlockTerraform = (($RegionFlags & $blockTerraformFlag) == $blockTerraformFlag);
Related
Taken from here: http://php.net/manual/en/function.base-convert.php#105414
function rome($N){
$c='IVXLCDM';
for($a=5,$b=$s='';$N;$b++,$a^=7)
for($o=$N%$a,$N=$N/$a^0;$o--;$s=$c[$o>2?$b+$N-($N&=-2)+$o=1:$b].$s);
return $s;
}
What is the purpose of XOR $a^0; here? (4th line)
Deleting it doesn't seem to make any difference. Check it out at: http://goo.gl/K6TwQI
You'll commonly see people use bitwise operators to implicitly convert expressions to an integer because of the way the underlying language works. This is mainly because these operations are blazing fast and avoid function calls, etc.
Because XOR doesn't affect the integer part of the variable, my best best is that this is just being used to ensure $a is always evaluated as an integer.
Here's an example.
I'm comparing two strings like so:
<?php
$Str1 = '111122223333444455556666';
$Str2 = '111122223333444455557777';
if($Str1 != $Str2){
// Do something
} else {
// Do something else
}
?>
Obviously, $Str1 is not the same as $Str2, but still always executes the else-block. I know that I should simply use === or !== to compare here, but I'm wondering why (basically) any other value I try does in fact evaluate the way it's expected to.
I also read this in the documentation "If the string does not contain any of the characters '.', 'e', or 'E' and the numeric value fits into integer type limits (as defined by PHP_INT_MAX), the string will be evaluated as an integer.", so I'm guessing it should not be below or the same as the value of PHP_INT_MAX (which is by far less than the strings I'm evaluating above) - assuming that's what they mean by "fits into". So why are the strings above being evaluated as being the same? Could it possibly be a PHP bug or is there something I'm missing?
I'm using PHP version 5.3.8 since yesterday, coming from PHP 5.3.6. Running on Windows XP.
What is happening here is that the numbers are cast to floats (as they don't fit into ints) and the floats happen to be the same. See the PHP source.
This script shows that the parsed floats indeed have the same value.
That's what it looks like, if I do this:
$Str1 = '111122223333444455556666 ';
$Str2 = '111122223333444455557777 ';
It comes out fine (note the space)
So it must be converting to number and not seeing the difference because of length
One could get the thought that PHP is bit relaxed in these conversions?!
Then again, do you rather want good old strict type-checking?
Not as advanced as above, but still enough to grab an hour of my time recently.
<?
$a_var = 0;
if ($a_var=="WHATEVER")
echo "WATCH OUT! This will be printed!";
//- as "whatever" is converted to an int
if ((string)$a_var=="WHATEVER")
echo "OK, this will of course not be printed!";
$a_var = "0";
if ($a_var=="WHATEVER")
echo "OK, this will of course also not be printed!";
?>
Conclusion: BEWARE of the automated casting in PHP.
It may play tricks on you now and then, and bugs may be very hard to track.
Explicit casting one time too many may be smarter at times, rather than relying on our great PHP understanding. ;-)
Use
if (strcmp($Str1, $Str2) == 0) {
//equal
} else {
//not equal
}
As mentioned in https://docstore.mik.ua/orelly/webprog/php/ch04_06.htm, first compare the two as String and then compares to 0 is there're equal.
I see that in PHP there are functions that can accept multiple options into a single argument, for example:
error_reporting(E_ERROR & E_WARNING);
I want to implement this kind of functionality into my javascript function. Do you know examples of functions that take this kind of arguments?
I'm totally confused about how does the function know what are the options that are passed...
(Assume it is instead: error_reporting(E_ERROR | E_WARNING); )
Well, it is a bitmask. So E_ERROR might be a number like this (in binary):
0010000
and E_WARNING might be:
0000010
and when they are combined with |, you get
0010010
(a single integer, with multiple bits set)
The function can then check which bits are set using the & bitwise operator. You can certainly do it in javascript, although it might be less common, and possibly less efficient and reliable as the numbers get bigger since javascript doesn't really have integers, they are really floating point numbers.
In javascript, you might prefer to use something like this:
error_reporting({warning: true, error: true});
(edited to show it in the more sensible way, with | not & to combine them)
Yes, it's possible, but it works with |.
var flag1 = 1,
flag2 = 2; // powers of 2
function get(flags) {
if((flags & flag1) === flag1) { // remove all other bits and check
alert('flag1'); // whether you get the flag itself
}
if((flags & flag2) === flag2) {
alert('flag2');
}
}
get(flag1 | flag2); // alerts both
You could of course create a helper function which does the chekcing so that you don't need those parentheses:
function contains(flags, flag) {
return (flags & flag) === flag;
}
http://jsfiddle.net/pimvdb/NpFYj/1/
It seems that simple comparison signs >,>= and their reverse components can evaluate if a certain variable is a number or not. Example $whatami='beast'; ($whatami<0)?echo 'NaN':echo 'is numeric!';
Are there cases where is_numeric() usage is necessary for positive values (number >0)? It seems that using comparison signs above would determine if the variable is numeric..
As I have been finding out, a lot of these helper functions are really necessary because PHP isn't strongly typed. I posted a similar question (although not that similar) about isset earlier this week. One thing to note is that PHP will change your string to its integer value for comparisons during some instances (when there are mixed types). This can't be overlooked. I think this is a strong case for is_numeric
from PHP Manual
If you compare a number with a string
or the comparison involves numerical
strings, then each string is converted
to a number and the comparison
performed numerically. These rules
also apply to the switch statement.
The type conversion does not take
place when the comparison is === or
!== as this involves comparing the
type as well as the value.
Another thing to think about is that "what is 0" in PHP. It means a lot. It's not always numeric. It may be a numeric string, boolean false, integer, etc... This is why those helper functions exist.
To add to my answer:
change your example:
$whatami='beast';
($whatami<5) ? echo 'less than 5' : echo 'more than 5';
PHP would change 'beast' to its integer equivalent and then do the comparison. This would give unintended results. If you really wanted something similar, you'd have to wrap it in another conditional:
$whatami='beauty';
if(is_numeric($whatami){
($whatami<5) ? echo 'less than 5' : echo 'more than 5';
} else {
exit('what, am I not pretty enough for a beast?');
}
Then you would get your intended result (as weird as it may be).
There is a big difference between "can evaluate if a certain variable is a number or not" and "evaluate if a certain variable is a positive number". Using the comparison signs require you to test it twice (Both > & <= or >= & <) and may not be immediately obvious. is_numeric means you only need a single test and makes it quite obvious what you are doing.
Also, a string will evaluate as 0, meaning it throws your idea out. Stick with the proper commands :)
As per comment: Well, in this case, you are asking for comparing is_numeric against a test for positive numbers, excluding 0. This is not the intent for is_numeric, so naturally it may not be necessary. If you do a mathematical check that involves 0 as the answer or as part of the range, you will need is_numeric, otherwise you won't need it. The first part of your question asks a different question, so:
It seems that simple comparison signs >,>= and their reverse components can evaluate if a certain variable is a number or not - Incorrect
Are there cases where is_numeric() usage is necessary for positive values (number >0)? - No
It seems that using comparison signs above would determine if the variable is numeric - No. They can determine if a variable is either a non-zero number or unknown, not numeric.
Comparison will depend on the type of data on the left side of the operator.
The important thing to remember is that PHP is not a strongly typed language. If you want to compare a number and ensure it is a number, then yes, is_numeric() would be a good check. For example,
echo (is_numeric($whatami) && $whatami < 0) ? 'number greater than zero' : 'NaN or negative';
However, this shouldn't be generalized. If you can comment more on what you are wanting to do, you may find a more detailed answer.
Yes, there are cases.
For instance:
var_dump("5aa" > 4); //bool(true)
var_dump("5aa" > 6); //bool(false)
As you can see, the conversion of "5aa" to int(5). Let's see what is_numeric gives:
var_dump(is_numeric("5aa")); //bool(false)
So, is_numeric is more strict. Whether it's necessary depends on your application.
Notice that are cases where a numeric string and a number are not exactly the same thing:
var_dump("255" & "2"); //string(1) "2"
var_dump(255 & 2); //int(2)
See bitwise operations:
Be aware of data type conversions. If both the left-hand and right-hand parameters are strings, the bitwise operator will operate on the characters' ASCII values.
I stumbled upon a very strange bit of PHP code. Could someone explain why this is happening? *****BONUS POINTS***** if you can tell my why this is useful.
<?php
if(0=='a'){
print ord(0)." should NEVER equal ".ord('a')."<br>";
}
if(false==0){
print "false==0<br>";
}
if('a'==false){
print "a==false<br>";
}
?>
And the resulting output:
48 should NEVER equal 97
false==0
In PHP, 'a' is not the ASCII character a, but the string a. In a numeric context, it is equal to 0. For instance intval('a') results in a value of 0.
This is useful because PHP is primarily used for processing text, and one might want to try the test (123 == '123'), which is true. And given that a number in single (or double) quotation marks is treated as the number, it doesn't make sense for a string with no numeric value to be treated as anything other than 0.
Oh yeah, one more thing. 'a' in a boolean context is true, not false. I believe this makes some types of text processing more natural, but I honestly can't think of an example at this late hour.
Well, there's always the PHP type cheat sheet for that!
This is a basic principle of weakly/dynamically typed languages called type juggling. Types will be cast to other types in certain circumstances. When you compare a string to a number, the string will be cast into a number. When comparing anything to a boolean, that value will be cast to a boolean.
There are rules for every type as to how it will be cast into another type or how it compares to other types. 'a' happens to be converted to 0 when cast to a number (the only logical choice, really). To avoid this type casting, test not with the equality operator ==, but with the identity operator ===.
As James pointed out, this is useful since PHP deals a lot with strings that are really numbers. For example, HTML forms only submit strings, even if the value is a number. It also allows for some really terse code, like:
$result = someOperation();
if (!$result) {
// $result may be null, false, 0, '' or array(),
// all of which we're not interested in
error();
}
It also means you have to be really careful about what to check for in which circumstances though, since a value might unexpectedly cast into something else. And admittedly, 'a' == 0 in itself is really a pitfall of type juggling rather than helpful. It's one of the situations where you have to be careful and test like if (is_numeric($var) && $var == 0).
ord() takes characters, so PHP turns 0 into '0'. And 0 is equal to false, even though it is not identical (===).
Check out the PHP type comparison tables from the manual. It's a really handy thing to have close at hand until you've internalised it and has been invaluable to my understanding of exactly what will evaluate to true and when.
Others have already answered the core of the question, but I think it's important to state that in PHP, the only non-empty string that does not evaluate to "true" with the == operator is "0" as PHP treats any string containing only numbers as an integer or float.
The rationale for this is that PHP is fairly loosely typed and tries to allow integers, strings, floats and boolean values to be interchangeable. A real-world and extremely common example of this is if you're using the mysql or PDO functions, strings are returned for everything, even if the underlying column is an integer.
Consider the following sql:
CREATE TABLE `test`.`pants` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`some_other_int` INT NOT NULL
) ENGINE = InnoDB;
INSERT INTO `test`.`pants` (`id`, `some_other_int`)
VALUES ('1', '1'), ('2', '0');
And the following code:
<?php
$c = mysql_connect('127.0.0.1', 'user', 'password');
mysql_select_db('test', $c);
$r = mysql_query('SELECT * FROM pants', $c);
while ($row = mysql_fetch_assoc($r)) {
var_dump($row);
foreach($row as $k=>$v) {
if (!is_string($v))
echo "field {$v} was not a string!\n";
}
}
The "field x was not a string!" message is never printed, even though every column in the database is an integer. Suppose you want to actually use the second row in that table.
<?php
$id = 2;
$r = mysql_query(sprintf('SELECT * FROM pants WHERE id=%s', mysql_real_esacpe_string($id)), $c);
$row = mysql_fetch_assoc($r);
// this is the important bit
if (0 == $row['some_other_int']) {
echo "It was zero!";
}
If the string "0" was not treated as the integer 0 for the comparison, the above code would never print "It was zero!". The programmer would be required to take responsibility for juggling the type of the value which comes out of the database. This is not desirable for a loosely typed language.
Strict equality including type is tested using the "Is really, truly, honest to god equal to" operator, which is represented by the symbol "===".
I don't see how ('a'==0) is helpful
$var = '123abc';
if (123 == $var)
{
echo 'Whoda thunk it?';
}
It comes down to PHP's implicit conversion rules.
I'm failing at thinking of a practical example, but that's the basic reason why you're seeing that behavior.
Expansion:
In your example, 'a' is converted to 0 (zero), for the comparison. Imagine that for the purpose of the comparison, it's equivalent to '0a'. (That's the numeral zero, not the letter 'o.')
Further expansion:
I thought there was a good example use case for this in the manual, but I failed to find it. What I did come across should help shed some light on this "illogical" situation.
PHP is first and foremost a Web
language, not a general-purpose
scripting language. Since the Web is
not typed and everything is a string,
I had to do things slightly
differently early on to make PHP do
what people expected. Specifically,
"123"==123 needs to be true in order
to not have to type cast every single
numeric user input.
http://bugs.php.net/bug.php?id=48012
That doesn't exactly answer the question, but it points in the general direction.
PHP is a loosely typed language, and allows you to compare values of different types without throwing errors, which makes it very easy to use but as you have found can cause some weird but logical outputs.
Your first example:
if(0=='a'){
print ord(0)." should NEVER equal ".ord('a')."<br>";
}
When two different types of values are compared, one value is first turned into the same type as another via a cast and then compared. In the example of Int and String the string is converted into Int. When PHP turns a letter into a string it takes all the first numeric characters and then chops of the rest: i.e '123123afraa' becomes 123123, '9a9' becomes 9. If the string does not start with numerals it is given the value of 0.
Therefor your example is really: 0===(string)'a' which is really 0===0 since 'a' does not start with a numeric. I think you were expecting PHP to return the value of 'a' in ASCII which it does not! This is really useful to sanitise strings, php rarely needs to deal with ascii values it is too high level for that. (Its for making websites!)
When a string is compared to a boolean a value of '' or '0' are false, all other values are true. This is useful so you can check if a value is 'empty':
url http://domain.com/?foo=
if ($_GET['foo']))
{
// do something
}
When an integer is compared to a boolean the values of 0 is false other values are true, this is pretty standard.
So, all in all you need to understand what happens when different types of variables are compared with the == operator. Also it is probably wise to realise that == is almost never what you want and using === (which will not typecast your values) is ALOT safer.
The code seems to emanate from a unit test for the purpose of catching failures, hence the seemingly weird comparisons. In the same light, it may be preparatory to the main unit test to confirm that the == operator is working properly - as it should.