Conversion to 64 bit int - php

So I am working in PHP to convert a Steam Id, which many of you may be familiar with. I have the following steam ID:
STEAM_0:1:1514332
Now, I need to convert this to the 64 bit version, which is also the community ID. After browsing Steams official release on this here: http://developer.valvesoftware.com/wiki/SteamID and after also looking many places online, I have found the following method works for this:
Let X,Y, and Z be defined by the Steam ID: STEAM_X:Y:Z
SteamCommunityID = (Z*2) + 76561197960265728 + Y
So it works! However, where seems to be a mismatch between my ACTUAL community ID, and the one I am generating
Actual: 76561197963294393
PHP generated: 76561197963294000
When reversing the equasion, to get my steam id from the community id, I get: 1514335.5
Here is a simple example of the php in question:
//STEAM_0:1:1514332
$a = (1514332 * 2) + 76561197960265728 + 1;
echo $a; //76561197963294000
Am I doing something wrong?

PHP don't have 64bit int on 32-bit binary. It is using floating point here. see how to have 64 bit integer on PHP?
The question include links to BC Math, which can be used for your problem.

Personally, I use the following code and it works perfectly for splitting the Steam ID and working out the 64-bit community ID:
$split = explode(":", $steamid); // STEAM_?:?:??????? format
$x = substr($split[0], 6, 1);
$y = $split[1];
$z = $split[2];
$w = ($z * 2) + 0x0110000100000000 + $y;
$w will be the correctly formatted ID. I thought this may be helpful since I found this trying to do the same thing :)

I have had the issue. I'm using xampp on windows and its using the 32bit version of php but i just finished making a working script :) it can convert 64bit steamid's to 32bit and back have a mess with it.
<?php
//Starting 64bit steamid
$steamid = "76561198086186258";
echo "Original 64bit steamid: $steamid";
//64bit steamid to 32bit below
$authserver = bcsub($steamid, '76561197960265728') & 1;
$authid = (bcsub($steamid, '76561197960265728')-$authserver)/2;
$steamid = "STEAM_0:$authserver:$authid";
echo "<br/>32bit steamid: $steamid";
//32bit steamid to 64bit below
$id = explode(":", $steamid);
$authserver = $id[1];
$steamid64 = $id[2];
$steamid64 = $steamid64 * 2;
$steamid64 = bcadd($steamid64, 61197960265728);
if ($authserver == 1){$steamid64 = $steamid64 + 1;};
$steamid64 = "765$steamid64";
echo "<br/>new 64bit steamid: $steamid64";
?>

try to add (string) before these calculations
$a = (string) (1514332 * 2) + 76561197960265728 + 1;
and it will work always;
demo
response: 76561197963294393

Using the BCMath extension, you can do the following:
bcadd(bcadd(bcmul('1514332', '2'), '76561197960265728'), 1)
Which is a conversion of the equation above. It returns a string and not an int, thus avoiding the 32bit int problem.

You are not doing anything wrong. The formula is correct (using a calculator I get the 'actual' number).
There must be either a rounding or calculating issue or a simple OS limit for it.

You may use the BC Math PHP extension. Here is a snippet:
//STEAM_0:1:1514332
$a = bcadd(bcadd((1514332 * 2), 76561197960265728), 1);
echo $a; //76561197963294393

Very old topic but just wanted to share how I solved it since I had 32bit PHP and no possibility of using BCMath on my host. (thanks SiPlus for solution)
Here's a snippet:
# Convert Steam ID to Steam64 ID
$idParts = explode(':', $tradeOwnerSteamId32);
$authServer = intval($idParts[1]);
$accountNumber = intval($idParts[2]);
$tradeOwnerSteamId64 = (string) $accountNumber * 2 + $authServer;
//And using it in URL
$depositorInventory = json_decode(file_get_contents("https://steamcommunity.com/profiles/[U:1:$tradeOwnerSteamId64]/inventory/json/730/2"), true);

Related

Converting base10 to base62 and back in PHP on a 32bit system

I found a previously asked question here, and am trying to implement Eineki's solution, however I'm on a 32bit system (I've installed Ubuntu 20.04 on an old laptop for testing). It was noted in the comments that the code wouldn't work on a 32bit system but there are workarounds, but they are not spelled out clearly enough for me. Unfortunately I'm pretty new with PHP and also with this website. I tried to comment there to ask for help and was told I couldn't because my account is new.
So here's how I modified that code, based on the instructions given in those comments. The instructions were:
Try to change the line occurence of $num % $b with fmod($num, $b) and
$num/$b (and similar ones) with intdiv($nub, $b).
function base10to62($num, $b=62) {
$base='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$r = fmod($num % $b) ;
$res = $base[$r];
$q = floor(intdiv($num/$b));
while ($q) {
$r = fmod($q % $b);
$q = floor(intdiv($q/$b));
$res = $base[$r].$res;
}
return $res;
}
function base62to10( $num, $b=62) {
$base='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$limit = strlen($num);
$res=strpos($base,$num[0]);
for($i=1;$i<$limit;$i++) {
$res = $b * $res + strpos($base,$num[$i]);
}
return $res;
$base3_string1 = "212012222102200121211101010110220202222222211121102101011101111110021111210000102211101010101110101010101010220110000110111010101010000010002020001010200000022111111111110011120201111110000002002002002001011011101010000110010000000000";
$base10test = base_convert($base3_string1, 3, 10);
$base62test = base10to62($base10test);
$base62returntest = base62to10($base62test);
echo ("My base3_string1 is: ".$base3_string1."<br>");
echo ("My base10 number is: ".$base10test."<br>");
echo ("My base62 number is: ".$base62test."<br>");
echo ("My base62return hash is: ".$base62returntest."<br>");
As you can see, I have a base3 number I'm converting to base10. I'm doing this because it looks like Eineki's function wants base10 input. The base10 number I'm trying to convert is 8080064204040204462880280000286008662604880682228402402248426842, but when I attempt this the return is 0 and when I try to change it back of course the result is 0 because the input is 0.
I'm guessing I've misinterpreted Eineki's instructions on how to convert his code to work on a 32bit system. If anyone can help me correct this it would be appreciated.

Float to bigint

Ok, so I have this float number :-
$floatval = '1.05143617E+18';
It's equivalent integer is :-
1051436170000000000
Using php, I'm trying to convert this float number to the required integer value.
Here is my try :-
$floatval = '1.05143617E+18';
var_dump(convert($floatval));
function convert($floatval)
{
$divided = explode('+', $floatval);
$first = floatval($divided[0]);
$second = intval($divided[1]);
$final = intval($first * pow(10, $second));
return $final;
}
Output :-
953738112
Whatever I try, the output is not coming as required. Where am I doing mistake?
Try this
intval(floatval($floatval));
It appears you are dealing with integer overflow, probably because you are running PHP on Windows and your system does not support 64 bit integers. You can avoid this issue by doing your calculations with functions from the bcmath extension. If you are running on Windows, PHP will have built-in support for bcmath as noted in the documentation here. Using bcmath, Your convert function could be implemented like this:
function convert($floatval)
{
$divided = explode('E+', $floatval);
$base = $divided[0];
$exp = $divided[1];
$final = bcmul($base, bcpow('10', $exp));
return $final;
}
On a different system where you did not have the integer overflow problem, one of the other cast-based solutions should work.
$floatval = (float) '1.05143617E+18';
$intval = (int) $floatval;
var_dump($intval);
Output: int(1051436170000000000)
(int)(float)$floatval; does the trick.

How does python converts mysql binary(16)

I have two apps one written in php and one in python and both of them use the same mysql database.
For the public id of the entries in some of the tables I use binary(16) fields(I can't change this, it must remain this way).
The question is how does python does the conversion of this binary field?
Let's take one of the entries as an example.
When I get it in php(from the db) the value of the public id is °•WiCÄ‘õ0Iò|–g, the same value is shown in SequelPro. But php myAdmin does a hex function over binary fields and shows 0bb09557691443c491f53049f27c9667. Now I managed in php to convert the binary to the value showed in php myAdmin and it works for all the entries but I've just noticed that python does another conversion. When I get the entry used in this example via python the public id is owwweye1rjnvt3i1d0ib18x3.
What I need to achieve is to convert in php what I get from MySql: °•WiCÄ‘õ0Iò|–g to what python sees: owwweye1rjnvt3i1d0ib18x3. The php app makes calls on the python one(not developed by me) and thus the id needs to be in the same format for a successfull call.
Any suggestions are welcomed. Thanks.
EDIT: If i send °•WiCÄ‘õ0Iò|–g from php to python and print it rigth away I get: °•WiCÄ‘õ0Iò|–g
Finally I've sorted this out.
Seems that python converts to base36 not hex as I've wrongly supposed.
I've tried to simply base_convert 0bb09557691443c491f53049f27c9667 from 16 to 36 but I've got owwweye1rk04k4cskkw4s08s. Not really what I needed but still a great step further as it started to look like owwweye1rjnvt3i1d0ib18x3.
This difference I supposed to appear because of the large values to be converted(loss of precision), so I've further researched and found the bellow function, written by Clifford dot ct at gmail dot com on the php.net website:
<?php
function str_baseconvert($str, $frombase=10, $tobase=36) {
$str = trim($str);
if (intval($frombase) != 10) {
$len = strlen($str);
$q = 0;
for ($i=0; $i<$len; $i++) {
$r = base_convert($str[$i], $frombase, 10);
$q = bcadd(bcmul($q, $frombase), $r);
}
}
else $q = $str;
if (intval($tobase) != 10) {
$s = '';
while (bccomp($q, '0', 0) > 0) {
$r = intval(bcmod($q, $tobase));
$s = base_convert($r, 10, $tobase) . $s;
$q = bcdiv($q, $tobase, 0);
}
}
else $s = $q;
return $s;
}
?>
I don't think others will come across this issue very often, but still if it happens hope they'll find this instead of burning their brains out like I did :))))

How to use 64 bit in PHP [duplicate]

To use modular exponentiation as you would require when using the Fermat Primality Test with large numbers (100,000+), it calls for some very large calculations.
When I multiply two large numbers (eg: 62574 and 62574) PHP seems to cast the result to a float. Getting the modulus value of that returns strange values.
$x = 62574 * 62574;
var_dump($x); // float(3915505476) ... correct
var_dump($x % 104659); // int(-72945) ... wtf.
Is there any way to make PHP perform these calculations properly? Alternatively, is there another method for finding modulus values that would work for large numbers?
For some reason, there are two standard libraries in PHP handling the arbitrary length/precision numbers: BC Math and GMP. I personally prefer GMP, as it's fresher and has richer API.
Based on GMP I've implemented Decimal2 class for storing and processing currency amounts (like USD 100.25). A lot of mod calculations there w/o any problems. Tested with very large numbers.
use this
$num1 = "123456789012345678901234567890";
$num2 = "9876543210";
$r = mysql_query("Select #sum:=$num1 + $num2");
$sumR = mysql_fetch_row($r);
$sum = $sumR[0];
have you taken a look at bcmod()? php has issues with integers over 2^31 - 1 on 32 bit platforms.
var_dump(bcmod("$x", '104659') ); // string(4) "2968"
I suggest you try BigInteger. If that doesn't work out, you may use SWIG to add C/C++ code for the big integer calculations and link it into your code.
I wrote a very small code for you that will surely work in case of big numbers-
<?php
$x = gmp_strval(gmp_mul("62574","62574")); // $x="3915505476"
$mod=gmp_strval(gmp_mod($x,"104659")); //$mod="2968"
echo "x : ".$x."<br>";
echo "mod : ".$mod;
/* Output:
x : 3915505476
mod : 2968
*/
?>
You simply have to use strings for storing big numbers and to operate on them use GMP functions in PHP.
You may check some good GMP functions in the official PHP manual here-
http://php.net/manual/en/ref.gmp.php
I found another solution, but the number will be stored as a string. As soon as you cast it back to a numeric, you'll be restricted to the precision of the underlying platform. On a 32 bit platform, the largest int you can represent as an int type is 2,147,483,647:
/**
* #param string $a
* #param string $b
* #return string
*/
function terminal_add($a,$b)
{
exec('echo "'.$a.'+'.$b.'"|bc',$result);
$ret = "";
foreach($result as $line) $ret .= str_replace("\\","",$line);
return $ret;
}
// terminal_add("123456789012345678901234567890", "9876543210")
// output: "123456789012345678911111111100"
$x = 62574 * 62574;
// Cast to an integer
$asInt = intval($x);
var_dump($asInt);
var_dump($asInt % 104659);
// Use use sprintf to convert to integer (%d), which will casts to string
$asIntStr = sprintf('%d', $x);
var_dump($asIntStr);
var_dump($asIntStr % 104659);
<?php
function add($int1,$int2){
$int1 = str_pad($int1, strlen($int2), '0', STR_PAD_LEFT);
$int2 = str_pad($int2, strlen($int1), '0', STR_PAD_LEFT);
$carry = 0;
$str = "";
for($i=strlen($int1);$i>0;$i--){
$var = $int1[$i-1] + $int2[$i-1] + $carry;
$var = str_pad($var, 2, '0', STR_PAD_LEFT);
$var = (string) $var;
$carry = $var[0];
$str = $str . $var[1];
}
$res = strrev($str.$carry);
echo ltrim($res,"0");
}
add($int1,$int2);
?>

Hexadecimal XOR with 2 values in PHP and JavaScript

I can't find the solution for very easy question.
Code in JavaScript:
var x = -1 ^ 0xF00F9344;
In this case x value is 267414715
Code in PHP:
$x = -1 ^ 0xF00F9344;
The result is -4027552581
Any idea, how to get 267414715 (correct) result in PHP?
While javascript bit operations are always 32-bit, php depends on the platform's word size:
on a 32-bit platform
$n = "11110000000011111001001101000100"
-1^$n = "00001111111100000110110010111011" = 267414715
on a 64 bit platform
$n = "0000000000000000000000000000000011110000000011111001001101000100"
-1^$n = "1111111111111111111111111111111100001111111100000110110010111011" = -4027552581

Categories