Skip to content

Instantly share code, notes, and snippets.

@roydejong
Last active May 1, 2022 19:38
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Embed
What would you like to do?
PHP: Parse raw input as a float, with best guess for the decimal character (dot or comma). Useful if you do not know original locale or when you are processing user input.
<?php
function parseFloatGuess($rawValue) {
if (!$rawValue) {
return 0;
}
$lastCommaPosition = strrpos($rawValue, ',');
$lastDotPosition = strrpos($rawValue, '.');
// Special case: Neither present
if ($lastDotPosition === false && $lastCommaPosition === false) {
return floatval($rawValue);
}
// Special case: Comma is at index zero (e.g. ",123" same as ".123" or "0.123")
if ($lastCommaPosition === 0 && $lastDotPosition === false) {
$rawValue = str_replace(',', '.', $rawValue);
return floatval($rawValue);
}
// Guess what decimal separator we are using, based on which char we see last
// For example, a string formatted as "123,456.00" has a dot last, so we'll guess US dot
// Another example, a string formatted as "123.456,00" has a comma last, so we'll guess EU comma
// But a string like "123,456" is rather ambiguous and we're also forced to guess EU comma dec
$decimalChar = ($lastCommaPosition > $lastDotPosition ? ',' : '.');
$thousandsChar = ($decimalChar === '.' ? ',' : '.');
// Special guess: If there's more than one type of a char, it's probably our thousands sep
// e.g. we should probably interpret "1,456,789" as "," being the thousands separator
if (substr_count($rawValue, ',') > 1) {
$decimalChar = '.';
$thousandsChar = ',';
} else if (substr_count($rawValue, '.') > 1) {
$decimalChar = ',';
$thousandsChar = '.';
}
// Either way, dispose of what we think is our thousands char, and change to dot decimal char
$rawValue = str_replace($thousandsChar, '', $rawValue);
$rawValue = str_replace($decimalChar, '.', $rawValue);
return floatval($rawValue);
}
var_dump(parseFloatGuess("0")); // int(0)
var_dump(parseFloatGuess("0.123")); // double(0.123)
var_dump(parseFloatGuess("0,123")); // double(0.123)
var_dump(parseFloatGuess("1,100.12")); // double(1100.12)
var_dump(parseFloatGuess("1.100.444,12")); // double(1100444.12)
var_dump(parseFloatGuess("1,100,555")); // double(1100555)
var_dump(parseFloatGuess(".123")); // double(0.123)
var_dump(parseFloatGuess(",456")); // double(0.456)
@bozghiyy
Copy link

bozghiyy commented Apr 1, 2021

Thanks!
Great idea for solving the problem when you cannot control what decimal char you are going to get.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment