I'm trying to port a php algorithm to perl but I struggle with one bit operator I'm not familiar with...
so the php code looks like this:
...
$var = '348492634';
print ~$var;
...
result: -348492635
doing the exact same thing in perl:
...
$var = '348492634';
print ~$var;
...
result: 18446744073361058981
I read a lot about the integer size depending on the architecture of the cpu, but I never found a working solution. Maybe I'm just using the wrong function in perl...
It's necessary for the logic to get same result as in the php script.
Thanks in advance
Seems that on your setup, PHP ints are 32bit signed while perl ints are 64bit unsigned.
This will probably do what you need on the given system but it is not guaranteed to work the same if you use it on another installation of perl.
$var = '348492634'; #hex!
print ~($var - 2**32) - 2**32;
The following will do for both $var='348492634' (which you claim to have) and $var=348492634 (which you did have):
unpack('l', ~pack('l', $var))
The quick and dirty conversion is:
print -($var+1); # like ~$var in PHP
If your perl is using 64-bit integers, this will only fail for $var=-18446744073709551616
(0x8000000000000000), which is a value you wouldn't use in 32-bit PHP anyway.
Related
I tried to do it like 5*log(7.5/2), but I think it's the wrong way, can anyone tell me how to do it right ?
In PHP, a base 10 logarithm is made using log10, not log (which is for natural logarithm i.e. base e). Note also that your comparison example in the comments is with 5.7, not 7.5. Try this instead:
echo 1+5*log10(5.7/2);
Output:
3.2742243000426
Demo on 3v4l.org
I'm integrating a PHP application with an API that uses permissions in the form of 0x00000008, 0x20000000, etc. where each of these represents a given permission. Their API returned an integer. In PHP, how do I interpret something like 0x20000000 into an integer so I can utilize bitwise operators?
Another dev told me he thought these numbers were hex annotation, but googling that in PHP I'm finding limited results. What kind of numbers are these and how can I take an integer set of permissions and using bitwise operators determine if the user can 0x00000008.
As stated in the php documentation, much like what happens in the C language, this format is recognized in php as a native integer (in hexadecimal notation).
<?php
echo 0xDEADBEEF; // outputs 3735928559
Demo : https://3v4l.org/g1ggf
Ref : http://php.net/manual/en/language.types.integer.php#language.types.integer.syntax
Thus you could perform on them any bitwise operation since they are plain integers, with respect to the size of the registers on your server's processor (nowadays you are likely working on a 64-bit architecture, just saying in case it applies, you can confirm it with phpinfo() and through other means in doubt).
echo 0x00000001<<3; // 1*2*2*2, outputs 8
Demo : https://3v4l.org/AKv7H
Ref : http://php.net/manual/en/language.operators.bitwise.php
As suggested by #iainn and #SaltyPotato in their respective answer and comment, since you are reading the data from an API you might have to deal with these values obtained as strings instead of native integers. To overcome this you would just have to go through the hexdec function to convert them before use.
Ref : http://php.net/manual/en/function.hexdec.php
Since you are receiving it from an API php will interpret it as a string
echo hexdec('0x00000008');
returns the integer 8
This should work.
I have a problem like this
when i eval this
$a='820725059 + 35 * 4082615 + 6209777 - 6476390779 * 3376849 + 3 - 8089 * 3967379273 - 0 * 55111452';
eval('return ('.$a.');');
i got this result -2.1901884886788E+16
instead of -21901884886788304
i know about BCMath, but how to calculate multiple operation like this?
Note:
My problem is about print out as BIG INT
Check if you are using 32bit or 64bit PHP
echo PHP_INT_SIZE; //4 is 32bit, 8 is 64bit
32bit won't handle this integer, for 64bit the result is -21901884886788304
if you have to use 32bit, try using GMP, and parse the integer yourself (good luck...)
Another solution is to write very basic Python program (or any other language that handles large numbers easily) and send it as an argument with exec function and let the other language to parse it for you (Python can handle very large numbers easily)
I assume that the line "how to calculate multiple operation like this?" means "how to write a calculator for arbitrary user-submitted math expressions?", which is why you use eval in first place.
If you use eval over unsanitized user-submitted input, you fail, remember this as a rule of thumb.
You just can't solve this with eval anyway, you have to use BCMath operations if you want to work with bignums.
Proper solution is to tokenize the input and construct the tree of math operations, essentially writing an interpreter for simple language for describing math expressions.
Here is result of 5 seconds of googling for something already done before: https://github.com/michellesanver/Calculator You can take her work and replace usage of plain math operators in classes like Addition with BCMath methods.
So, I have a PHP script:
<?
rand(1000000000000,9999999999999);
The expected result is a number with 13 digits.
But it's returning some weird numbers, as:
987419207
1032717476
-455563764
Does anyone know what's going on?
PHP: 5.2.17
OS: Tested on Debian Squeeze and Windows 7, both 64 bits
Solution (workaround)
<?
echo rand(10000,99999).rand(10000000,99999999);
Use getrandmax() to see the max value that you can get from rand(), its clearly a overflow problem.
you could use 2 of this int and make a longer one, calling rand for a 6 digit and again for a 7 digits, just an idea.
i think 10000000000000 its not a valid integer!
output
getrandmax();
Use a bignum library like BCMath or GMP. GMP is newer and seems to have a better API but that's just my opinion
I am including the same "random.inc" in foo.php and bar.php. For each, I want reproducible "random" results.
So in foo.php I always want one set of numbers and/or keywords. In bar.php another. Which shouldn't change on reload. That's what I mean by contant pseudo-random. And that's why I seeding on the url. However I still get different results for individual numbers as well as for array pickson every reload. This is the full php file:
<?
header('Content-Type: text/plain');
$seed = crc32( $_SERVER['REQUEST_URI'] );
echo "phpversion: ".phpversion()."\nseed: $seed\n";
srand( $seed ); // (seed verified to be contant as expected)
// neither single values nor array pics turn out deterministic
echo ''.rand(0,100).' '.rand(0,100).' '.rand(0,100)."\n";
$values = array( '0'=>21,'1'=>89,'2'=>96,'3'=>47,'4'=>88 );
print_r( array_rand( $values, 3 ) );
?>
In the days of PHP4.1 it was (verified) possible to achieve constant pseudo-random like this. array_rand API documentation describes as a feature that since 4.2 initialization happens automatically. Perhaps this is overriding any explicit seeding? (if so, perhaps explicit seeding should raise an internal PHP flag, preventing automatic seeding?). Btw: mt_srand() and srand() are equally not working.
I would really like to get my deterministic / constant pseudo-random back...
Update: Solution below (Windows and/or version 5.2 's fault)
Works for me (PHP/5.3.6):
<?php
$data = range(1, 100);
srand(1);
print_r(array_rand($data, 3));
... always prints:
Array
(
[0] => 21
[1] => 89
[2] => 95
)
... in my machine. Apparently, the exact numbers differ depending on the exact environment but they're reproducible.
Guys, you are all correct! (Sorry, I answer it myself now)
my web hoster runs 5.2.17 under Linux 2.6.36, and above problem exists.
under Win x64 5.3.0 everything works as expected.
So it's everyone's guess if that's an OS related bug and/or a PHP bug, fixed in 5.3.0.
Given that random constant seeding worked before, I am guessing they fixed in 5.3 the bug that came with the autoseed feature enhancement in 4.2. Anyway, Thanx again, at least there's clarity now.
The seeding functions are still available, and should still work; it's just since PHP 4.2 they are automatically seeded with the time on page load; but you can still call them to reset the random sequence to a known starting point.
[edit] I have just done a quick test program to make sure I wasn't imagining it!
mt_srand(50000);
print "rand="+mt_rand(0,10000);
Using PHP 5.2, this always results in the same value being printed (1749).
[EDIT]
As noted by #cwd and in the accepted answer to this question, there appears to be a discrepancy in PHP 5.2's behaviour with random number seeding between the Linux and Windows versions. In PHP 5.2 on Linux, the above technique does not appear to work.
Fortunately, the bug seems to have been fixed in PHP 5.3, so the solution to this problem is simply to upgrade. (PHP 5.2 is not supported any longer, so you should upgrade anyway)
Btw, if anyone else wants "constant windows-pre-5.3 pseudo-random" (of low quality, e.g. for stuff like SEO buzzwording) this is a tested workaround:
$r = abs(crc32($URL))%20; // a number between 0 and 19, based on URL
In PHP 5.2.17 and probably on all versions of PHP 5.2, (not sure about windows), we lose the capability of generating random numbers based on a seed as PHP changes the algorithm used for random numbers.
rand and mt_rand are "broken" not only because they will not give one random number, but they will also not give a same sequence of random numbers - even when using a seed!
At first the PHP developers tried to argue that this is the way that it "should" work, but we can guess they caught enough grief about the problem that they have reverted the way that it works with PHP 5.3.
See the php mt_rand page and the bug tracker to learn about this issue.