PHP Math

Rounding, base conversion, random numbers and float pitfalls.

Intermediate
Key PointsNever compute money with floats — `0.1 + 0.2 != 0.3`.

Rounding

PHP
<?php
echo floor(3.7), " ", ceil(3.2), " ", round(3.5), " ", round(3.4), "\n";
echo round(3.14159, 2), " ", round(1234.5678, -2), "\n";
echo abs(-5), " ", max(1, 5, 3), " ", min(1, 5, 3), "\n";
echo intdiv(10, 3), " ", 10 % 3, "\n";
echo fmod(10.5, 3), "\n";
echo (int)3.9, "\n";
Output
3 4 4 3
3.14 1200
5 5 1
3 1
1.5
3
round rounds half away from zero, not banker's rounding. Financial calculations needing half-to-even must implement it.

Float pitfalls

PHP
<?php
var_dump(0.1 + 0.2);
var_dump(0.1 + 0.2 == 0.3);

// 正确比较:用误差范围
var_dump(abs((0.1 + 0.2) - 0.3) < PHP_FLOAT_EPSILON);

// 正确做法:整数分
$price = 1999;      // 19.99 元
$qty   = 3;
echo $price * $qty, "\n";
echo number_format($price * $qty / 100, 2), "\n";
Output
float(0.30000000000000004)
bool(false)
bool(true)
5997
59.97
0.1 + 0.2 is 0.30000000000000004 — inherent to IEEE 754, not a PHP bug. **Store money as integer cents or use bcmath.**

Arbitrary precision

PHP
<?php
echo bcadd("0.1", "0.2", 2), "\n";
echo bcsub("1.00", "0.99", 2), "\n";
echo bcmul("19.99", "3", 2), "\n";
echo bcdiv("1", "3", 10), "\n";
echo bcpow("2", "10"), "\n";

var_dump(bccomp("1.00", "1.0", 2));
Output
0.30
0.01
59.97
0.3333333333
1024
int(0)

bcmath takes and returns strings, with a scale argument. Never pass floats — precision is already lost before the call.

Base conversion

PHP
<?php
echo decbin(10), " ", decoct(10), " ", dechex(255), "\n";
echo bindec("1010"), " ", octdec("12"), " ", hexdec("ff"), "\n";
echo base_convert("ff", 16, 2), "\n";
echo base_convert("zz", 36, 10), "\n";
Output
1010 12 ff
10 10 255
11111111
1295

Randomness

FunctionUseSecure
random_int整数随机是
random_bytes随机字节是
mt_rand一般随机(抽奖展示、排序)否
shuffle打乱数组否
array_rand随机取键否
PHP
<?php
echo random_int(1, 6), "\n";
echo strlen(bin2hex(random_bytes(16))), "\n";

$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
$token = "";
for ($i = 0; $i < 8; $i++) {
    $token .= $chars[random_int(0, strlen($chars) - 1)];
}
echo strlen($token), "\n";
Output
6
32
8
**Tokens, captchas and reset links must use random_int / random_bytes.** mt_rand is predictable — using it for tokens means no security at all.

Friends & Partners