An accurate PHP helper for parsing numbers from strings with support for various thousands and decimal separators.
Package Version | PHP Version |
---|---|
v2.x | ^8.1 |
v1.x | ^8.0 |
$ composer require 514sid/num
The built-in PHP functionsintval()
andfloatval()
,along with typecasting, may not always correctly handle varying numeric value formats based on regional standards.
floatval("1 234 567.89") // float(1)
intval("1,234.56") // int(1)
With theNum
helper, you can achieve the desired functionality.
You have the option to provide the decimal separator to theint()
orfloat()
methods.
Alternatively, you can allow theNum
helper to make an educated guess if you're unsure about the exact separator used in a specific string representing a numeric value.
useNum\Num;
useNum\Enums\DecimalSeparator;
Num::float('1,234,567.89',DecimalSeparator::POINT) // float(1234567.89)
Num::float('1.234.567,89',DecimalSeparator::COMMA) // float(1234567.89)
// or
Num::float('1,234,567.89') // float(1234567.89)
Num::float('1.234.567,89') // float(1234567.89)
Num::float(123) // float(123.0)
Num::int('1,234,567.89') // int(1234567)
Num::int('1.234.567,89') // int(1234567)
Num::int(123.45) // int(123)
Num::float('text') // float(0.0)
Num::int('text') // int(0)
Num::int('1.23e3') // int(1230)
Num::float('-5.67e-4') // float(-0.000567)
When you pass a decimal separator as the second argument to theint()
orfloat()
static methods, they remove everything from the string except digits and the decimal separator, and then perform typecasting using PHP's built-in functionality.
If you do not specify a decimal separator, theNum
helper tries to guess it using theDecimalSeparatorGuesser
,which relies on formatting conventions from the Wikipedia article:https://en.wikipedia.org/wiki/Decimal_separator.
I am still working on improvingDecimalSeparatorGuesser
,so it might not be 100% accurate.
In most locales, for numbers smaller than 100000, a thousand separator is used based on powers of 1000.
This means that if a string is provided with only one dot or comma and there are 3 digits following it, the guesser will treat this number as a whole number; otherwise it will treat it as a float.
useNum\Num;
Num::float('12.34567') // float(12.34567)
Num::float('12.34') // float(12.34)
Num::float('12.345') // float(12345.0)
Num::float('1234,567') // float(1234.567)
useNum\Casts\NumInt;
useNum\Casts\NumFloat;
protected$casts= [
'integer'=>NumInt::class,
'float'=>NumFloat::class,
];