Bug #74655 [Opn->Nab]: parse int and float distort data
Edit report at https://bugs.php.net/bug.php?id=74655&edit=1
ID: 74655
Updated by: danack@php.net
Reported by: an dot nguyen-hoai at lazada dot com
Summary: parse int and float distort data
-Status: Open
+Status: Not a bug
Type: Bug
Package: Math related
Operating System: Docker Ubuntu
PHP Version: 7.0.19
Block user comment: N
Private report: N
New Comment:
Floating point values have a limited precision. Hence a value might
not have the same string representation after any processing. That also
includes writing a floating point value in your script and directly
printing it without any mathematical operations.
If you would like to know more about "floats" and what IEEE
754 is, read this:
http://www.floating-point-gui.de/
Thank you for your interest in PHP.
you don't need such a long example:
echo ((int)(17.99 * 100));
output is 1798
Floating point numbers aren't appropriate to store exact values. Writing 17.99 actually gets
represented in code as 17.989999771118164 according to https://www.h-schmidt.net/FloatConverter/IEEE754.html
Casting floats to ints rounds down.
Either you should be storing numbers as ints, and then displaying them with the appropriate number
of decimal points if they are prices, or you could consider rounding functions.
Previous Comments:
------------------------------------------------------------------------
[2017-05-26 09:47:48] an dot nguyen-hoai at lazada dot com
Description:
------------
<?php
declare(strict_types=1);
namespace App\Traits;
/**
* Class SanitizerHelper
*
* @package App\Traits
*/
trait SanitizerHelperTrait
{
/**
* @param array $data
* @param array $fields
*
* @return array
*/
public function decimalFormat(array $data, array $fields)
{
foreach ($fields as $field) {
$value = array_get($data, $field, null);
if ($value) {
$value = ((float) $value) * 100;
$data[$field] = (int) $value;
}
}
return $data;
}
}
Test script:
---------------
<?php
namespace Tests\Unit\Traits;
use App\SanitizerHelperTrait;
/**
* Class SanitizerHelperTest
*
* @package Tests\Unit\Traits
*/
class SanitizerHelperTest extends \PHPUnit_Framework_TestCase
{
use SanitizerHelperTrait;
/**
* @param $data
* @param $expected
*
* @covers \App\Traits\SanitizerHelperTrait::decimalFormat()
* @dataProvider getDecimalDataProvider
*/
public function test_Decimal_Format($data, $expected)
{
static::assertEquals($expected, $this->decimalFormat($data, array_keys($data)));
}
public function getDecimalDataProvider()
{
return [
'#1 decimal' => [
'data' => [
'discountAmount' => 17.99,
],
'expected' => [
'discountAmount' => 1799,
],
],
'#2 decimal' => [
'data' => [
'arAmount' => 10.02,
],
'expected' => [
'arAmount' => 1002,
],
],
'#3 decimal' => [
'data' => [
'gotAmount' => 10.02,
],
'expected' => [
'gotAmount' => 1002,
],
],
'#5 No decimal' => [
'data' => [
'arAmount' => 200,
],
'expected' => [
'arAmount' => 20000,
],
],
'#6 Null' => [
'data' => [
'arAmount' => null,
],
'expected' => [
'arAmount' => 0,
],
],
];
}
}
Expected result:
----------------
1799
Actual result:
--------------
1798
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=74655&edit=1
Thread (2 messages)