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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks!
Great idea for solving the problem when you cannot control what decimal char you are going to get.