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.
Related
Recently I wanted to search an array for numeric values (ints, doubles, and numbers with exponent notation) as quickly as possible.
I initially used 'is_numeric()' as we often use that as our goto for checking but I wanted to see if I could put in something faster.
I noticed that if I cast to float then as long as the value is numeric PHP will produce a value other than zero. So using the bitwise operators I can do a logical NOT zero within the if statement surrounding the search.
if (~(~(float)$value)) {
// add to result array
}
After initial testing I found things seemed to speed up by 2 whole seconds with a moderately sized array of numerics and non numerics. However this was little more than a simple unit test.
Does anyone have experience of performance of casting as a float vs is_numeric? I know they're probably not 100% functionally equivalent (I think the cast to float would convert hexadecimal) but for my purposes I'm only going to be casting ints, doubles and numbers with an exponent notation. Is this a performance gain over is_numeric() or have I imagined this?
warning!
isnumeric () is not just a whim, I am attaching a small piece of code that shows you the error that your conversion type makes. in many attacks on php there are strings that can be both numbers and squeaks where the attackers inject bad code.
code:
<?php
$a="1809809808908099878758765<?php echo \"I powned you\"; ?>";
echo is_numeric($a)?"yes":"no"; // out no
echo "\n";
echo (~(~(float)$a))?"Yes":"No"; // out Yes
if you do it that way you could gain performance but depending on what you have to do you could open a hole in security!
I am writing a function that accepts a numeric string as argument, then does some calculations with it and returns it.
As you probably noted, I am doing calculations with a string. Although it works without problems in PHP, I know that other language would throw an error. That leads to my question:
Should I cast the string to an integer before my calculations, then calculate with the int and cast the result back again to a string? Would that be a cleaner style somehow? Or is it really ok to be 'type unspecific' in PHP?
I'll advise you to check if the arguments are numeric with is_numeric(). I think it's important to handle improper function calls. Also I don't see any reason to cast operands for calculation — PHP will do it for us. But I would prefer to return the result of a particular type for predictable JSON serialization or DB driver's behavior.
function calc($a, $b) {
if (!ctype_digit($a) || !ctype_digit($b)) {
throw new \InvalidArgumentException('A and B must be an integers');
}
return (string) ($a + $b);
}
PHP is a loosely-typed language so you will have no trouble performing calculations with string data because the parser performs type-juggling for you.
Do note that if you are getting into very precise calculations which require extensive float accuracy then you will need to use the BC Math Library
From a programming perspective, it might be better to think about why you want to use numeric strings for calculations. Why not use integer input as well as integer output?
I browsed through several similar questions, but they all only state the fact:
If ... comparison involves numerical strings, then each string is converted to a number and the comparison performed numerically.
Okay, I got it. It explains what is going on when '00001' == '1' returns TRUE.
The question is: Why PHP does so?
What is the reason for probing strings for being numeric, and then casting if so? Why can't we just compare two strings already?
I can fairly understand what casting is required if two operands has different types. But why it does "usual math" when both are strings?
You can compare two strings.
"00001" === "1" // false
Remember == means equivalent === means equal
My only guess as to why this is the case is because in the beginning PHP strived to be a type-less language before they went the route of becoming a loosely typed language.
PHP was originally string processor that allowed for a little scripting inside of it. Since all inputs on the web are textual in nature it had to work hard given textual input to behave sanely when it came to dealing with numbers.
I could be wrong about this but I don't believe the ability to explicitly cast data types entered the stage until PHP 4 with the introduction of the *val functions (like intval) etc. and I think the casting notation, like (int) came around after that.
For the non comparison operations it was pretty easy because they all have a type associated with them (+ - / * all deal with numbers whereas . deals with strings) so a clear path to how things should be cast in those cases is apparent.
But with equality or equivalence checks between variables then the only way to do that was to treat everything that looked like a number as a number because at the time the only way it could be gotten would be by externally would be as a string and there was no way to make it otherwise.
Because, PHP produce a product for End-Users, not for Application Developers.
So when you produce such product like below:
if (isset($_POST['submit'])){
if ($_POST['myinput'] == "1") echo 'Yes'; //or == 1
else echo 'NO';
}
?>
<form name="myform" method="POST" action="">
<input name="myinput">
<input name="submit" type="submit">
</form>
If the user enter 1 or 0001, what do you expect to print in both case? Yes or NO?
the answer is clear. we expect to see Yes. so this is why PHP does so
If for any rare reason, we need to definitely compare them, then we should change == to ===
Ah, finally I got it. It was quite stupid of me.
Comparison involves not only "is equal" but also "less than" and "greater than". And for the latter two it is obviously critical to cast numerical operands before comparison, because numbers often being represented in PHP as strings, and 11 have to be greater than 9 even if both stored in strings.
So, as compare_function() does all the comparisons at once, returns either 1, 0, -1 to tell if first operand is bigger, equal or less than second respectively - well, it's fairly explains, why operands being cast.
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);
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.