Bug #74655 [Opn->Nab]: parse int and float distort data

From: Date: Fri, 26 May 2017 10:04:18 +0000
Subject: Bug #74655 [Opn->Nab]: parse int and float distort data
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-209266@lists.php.net to get a copy of this message
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)

« previous php.bugs (#209266) next »