Skip to content

Instantly share code, notes, and snippets.

@mfdj
Created August 13, 2017 22:03
Show Gist options
  • Save mfdj/f5c2f4fb55baeefc66c757dfce05ee10 to your computer and use it in GitHub Desktop.
Save mfdj/f5c2f4fb55baeefc66c757dfce05ee10 to your computer and use it in GitHub Desktop.
prove how to safely validate precision
<?php
set_error_handler(function($severity, $message, $filename, $lineno) {
throw new \Error($message, $severity);
});
function strictAssert($expected, $actual) {
if ($actual !== $expected) {
echo PHP_EOL . '✋' . PHP_EOL;
var_dump($actual, $expected);
die;
}
}
function because(string $proposition, callable $test) {
echo "$proposition";
try {
$test();
} catch (\Throwable $e) {
echo PHP_EOL . $e->getMessage() . PHP_EOL;
die;
}
echo " 👍" . PHP_EOL;
}
echo 'Becasue …' . PHP_EOL;
because("commas in strings ruin float conversion", function() {
strictAssert( (float) '2000.45', 2000.45 );
strictAssert( (float) '2,000.45', 2.0 );
});
because("weird types and values will actually coerce", function() {
strictAssert( (float) '', 0.0 );
strictAssert( (float) '2,000.45', 2.0 );
});
because("floats compact leading and trailing zeros", function() {
strictAssert( (string) 1.100, '1.1' );
strictAssert( (string) 00.35, '0.35' );
});
because("number_format coerces to float and will warn about some confusing values/types", function() {
// number_format considers bool|null to be safely coercible, though I find this to be an odd excecption
strictAssert( number_format(null, 2), '0.00' );
strictAssert( number_format(false, 2), '0.00' );
strictAssert( number_format(true, 2), '1.00' );
// number_format warns about ambigous values
try {
$result = number_format('');
} catch (\Throwable $e) {
strictAssert($e->getmessage(), 'number_format() expects parameter 1 to be float, string given');
}
// note: warnings won't evaluate to a result
// also-note: typically warnings won't halt execution (tricky)
strictAssert(!isset($result), true);
try {
number_format('2,000.45');
} catch (\Throwable $e) {
strictAssert($e->getmessage(), 'A non well formed numeric value encountered');
}
try {
number_format([0,1,2]);
} catch (\Throwable $e) {
strictAssert($e->getmessage(), 'number_format() expects parameter 1 to be float, array given');
}
});
because("number_format will round based on precision", function() {
strictAssert( number_format(0.2349, 2), '0.23' );
strictAssert( number_format(0.235, 2), '0.24' );
});
because("number_format will add commas", function() {
strictAssert( number_format(999, 2), '999.00' );
strictAssert( number_format(1000, 2), '1,000.00' );
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment