Fix number formatting with different settings of precision in PHP
- fixed Util::formatNumber to avoid rounding issues to mess up display - force precision = 14 to ensure we get sane behavior With precision set to higher value many things do not behave as expected producing strange numbers in various places. For example with precision=19 you get: php > echo round(1.2, 2); 1.199999999999999956 Fixes #12303 Signed-off-by: Michal Čihař <michal@cihar.com>
This commit is contained in:
parent
f3babbb945
commit
f3ca367efa
@ -19,6 +19,7 @@ phpMyAdmin - ChangeLog
|
||||
- issue #12251 Automatically save SQL query in browser local storage rather than in cookie
|
||||
- issue #12292 Unable to edit transformations
|
||||
- issue #12502 Remove unused paramenter when connecting to MySQLi
|
||||
- issue #12303 Fix number formatting with different settings of precision in PHP
|
||||
|
||||
4.6.4 (2016-08-16)
|
||||
- issue [security] Weaknesses with cookie encryption, see PMASA-2016-29
|
||||
|
||||
@ -1604,17 +1604,13 @@ class Util
|
||||
$value = round($value / (self::pow(1000, $d, 'pow') / $dh)) /$dh;
|
||||
$unit = $units[$d];
|
||||
|
||||
// If we don't want any zeros after the comma just add the thousand separator
|
||||
if ($noTrailingZero) {
|
||||
$localizedValue = self::localizeNumber(
|
||||
preg_replace('/(?<=\d)(?=(\d{3})+(?!\d))/', ',', $value)
|
||||
);
|
||||
} else {
|
||||
//number_format is not multibyte safe, str_replace is safe
|
||||
$localizedValue = self::localizeNumber(
|
||||
number_format($value, $digits_right)
|
||||
);
|
||||
// number_format is not multibyte safe, str_replace is safe
|
||||
$formattedValue = number_format($value, $digits_right);
|
||||
// If we don't want any zeros, remove them now
|
||||
if ($noTrailingZero && strpos($formattedValue, '.') !== false) {
|
||||
$formattedValue = preg_replace('/\.?0+$/', '', $formattedValue);
|
||||
}
|
||||
$localizedValue = self::localizeNumber($formattedValue);
|
||||
|
||||
if ($originalValue != 0 && floatval($value) == 0) {
|
||||
return ' <' . self::localizeNumber((1 / self::pow(10, $digits_right)))
|
||||
|
||||
@ -107,6 +107,13 @@ PMA_checkExtensions();
|
||||
ini_set('default_charset', 'utf-8');
|
||||
mb_internal_encoding('utf-8');
|
||||
|
||||
/**
|
||||
* Set precision to sane value, with higher values
|
||||
* things behave slightly unexpectedly, for example
|
||||
* round(1.2, 2) returns 1.199999999999999956.
|
||||
*/
|
||||
ini_set('precision', 14);
|
||||
|
||||
/**
|
||||
* the relation lib, tracker needs it
|
||||
*/
|
||||
|
||||
@ -6,6 +6,13 @@
|
||||
* @package PhpMyAdmin-test
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set precision to sane value, with higher values
|
||||
* things behave slightly unexpectedly, for example
|
||||
* round(1.2, 2) returns 1.199999999999999956.
|
||||
*/
|
||||
ini_set('precision', 14);
|
||||
|
||||
// Let PHP complain about all errors
|
||||
error_reporting(E_ALL);
|
||||
|
||||
|
||||
@ -70,6 +70,30 @@ class PMA_FormatNumberByteDown_Test extends PHPUnit_Framework_TestCase
|
||||
array(0.003, 3, 3, '3 m'),
|
||||
array(-0.003, 6, 0, '-3,000 µ'),
|
||||
array(100.98, 0, 2, '100.98'),
|
||||
array(21010101, 0, 2, '21,010,101.00'),
|
||||
array(20000, 2, 2, '20 k'),
|
||||
array(20011, 2, 2, '20.01 k'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Core test for formatNumber
|
||||
*
|
||||
*
|
||||
* @param float $a Value to format
|
||||
* @param int $b Sensitiveness
|
||||
* @param int $c Number of decimals to retain
|
||||
* @param array $d Expected value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function assertFormatNumber($a, $b, $c, $d)
|
||||
{
|
||||
$this->assertEquals(
|
||||
$d,
|
||||
(string) PMA\libraries\Util::formatNumber(
|
||||
$a, $b, $c, false
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -87,12 +111,21 @@ class PMA_FormatNumberByteDown_Test extends PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testFormatNumber($a, $b, $c, $d)
|
||||
{
|
||||
$this->assertEquals(
|
||||
$d,
|
||||
(string) PMA\libraries\Util::formatNumber(
|
||||
$a, $b, $c, false
|
||||
)
|
||||
);
|
||||
$this->assertFormatNumber($a, $b, $c, $d);
|
||||
|
||||
// Test with various precisions
|
||||
$old_precision = ini_get('precision');
|
||||
ini_set('precision', 20);
|
||||
$this->assertFormatNumber($a, $b, $c, $d);
|
||||
ini_set('precision', 14);
|
||||
$this->assertFormatNumber($a, $b, $c, $d);
|
||||
ini_set('precision', 10);
|
||||
$this->assertFormatNumber($a, $b, $c, $d);
|
||||
ini_set('precision', 5);
|
||||
$this->assertFormatNumber($a, $b, $c, $d);
|
||||
ini_set('precision', -1);
|
||||
$this->assertFormatNumber($a, $b, $c, $d);
|
||||
ini_set('precision', $old_precision);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user