This seems to work:
function safe_round($x, $dp) { $x *= pow(10,$dp); $x = explode('.',(string)$x); $res = (int) $x[0]; if ( (count($x)>1) && ($x[1][0] >= 5) ) { $res++; } return $res/100; }
In other words: safe_round(1.605,2) stepped through gives 1.605 * 10^2 = 160.5 160.5 => "160.5" => ("160","5") $res = 160 if something after "." and the first digit of that is 5 or higher (it is here): $res++ (=161) return $res/100 = 1.61
This relies on the fact that PHP seems to "work" when you convert the float to a string.
Any reasons why this shouldn't work in general? ($x<0 would be a test case I haven't considered).