PHP Gotcha: Bigint with sprintf()
December 3rd, 2008 by Erik
Today I am working on modification of an FB application to permit installation on “pages” in addition to profiles. Facebook has switched (several months ago) to using 64bit integer values for id’s site wide. In the code I use sprintf to create stored procedure calls and couldn’t figure out why the values the the database weren’t matching up with my expectations… the following code would output 536035818 instead of the much larger 30600806890 value I expected. Clearly this is a 32bit vs 64bit.
$big_int = 30600806890; $format = "%d"; $new_string = sprintf($format, $big_int); print $new_string; |
Since updating to a fully 64 bit platform and so on really isn’t an option, I needed a work around. I composed a quick test for my value and ran it. The test as you can see, it provides output for each of the valid substitution types in sprintf.
$big_int = 30600806890; $type = array("%b","%c","%d","%e","%u","%f","%F","%o","%s","%x","%X"); for($i=0;$i<count($type);$i++){ print $type[$i] . ": " . sprintf($type[$i], $big_int) . "\n"; } |
This results with the list below. Obviously floating point numbers and strings are the only way to handle these bigint values. A simple drop in value is of course to swap %s for %d as needed, but you lose some type catching which may cause security issues. Instead, I recommend using %0.0f which will suppress the decimal portion - keeping the int an int - while keeping the numeric type checking intact.
%b: 11111111100110100000111101010 %c: ? %d: 536035818 %e: 3.06008e+10 %u: 536035818 %f: 30600806890.000000 %F: 30600806890.000000 %o: 3774640752 %s: 30600806890 %x: 1ff341ea %X: 1FF341EA