# PHP BC Math (Binary Calculator) Using bcmath to read/write a binary long on 32-bit system

## Example

On 32-bit systems, integers greater than `0x7FFFFFFF` cannot be stored primitively, while integers between `0x0000000080000000` and `0x7FFFFFFFFFFFFFFF` can be stored primitively on 64-bit systems but not 32-bit systems (`signed long long`). However, since 64-bit systems and many other languages support storing `signed long long` integers, it is sometimes necessary to store this range of integers in exact value. There are several ways to do so, such as creating an array with two numbers, or converting the integer into its decimal human-readable form. This has several advantages, such as the convenience in presenting to the user, and the ability to manipulate it with bcmath directly.

The `pack`/`unpack` methods can be used to convert between binary bytes and decimal form of the numbers (both of type `string`, but one is binary and one is ASCII), but they will always try to cast the ASCII string into a 32-bit int on 32-bit systems. The following snippet provides an alternative:

``````/** Use pack("J") or pack("p") for 64-bit systems */
function writeLong(string \$ascii) : string {
if(bccomp(\$ascii, "0") === -1) { // if \$ascii < 0
// 18446744073709551616 is equal to (1 << 64)
// remember to add the quotes, or the number will be parsed as a float literal
}

// "n" is big-endian 16-bit unsigned short. Use "v" for small-endian.
return pack("n", bcmod(bcdiv(\$ascii, "281474976710656"), "65536")) .
pack("n", bcmod(bcdiv(\$ascii, "4294967296"), "65536")) .
pack("n", bcdiv(\$ascii, "65536"), "65536")) .
pack("n", bcmod(\$ascii, "65536"));
}

function readLong(string \$binary) : string {
\$result = "0";
\$result = bcadd(\$result, unpack("n", substr(\$binary, 0, 2)));
\$result = bcmul(\$result, "65536");
\$result = bcadd(\$result, unpack("n", substr(\$binary, 2, 2)));
\$result = bcmul(\$result, "65536");
\$result = bcadd(\$result, unpack("n", substr(\$binary, 4, 2)));
\$result = bcmul(\$result, "65536");
\$result = bcadd(\$result, unpack("n", substr(\$binary, 6, 2)));

// if \$binary is a signed long long
// 9223372036854775808 is equal to (1 << 63) (note that this expression actually does not work even on 64-bit systems)
if(bccomp(\$result, "9223372036854775808") !== -1) { // if \$result >= 9223372036854775807
\$result = bcsub(\$result, "18446744073709551616"); // \$result -= (1 << 64)
}
return \$result;
}
`````` PDF - Download PHP for free