php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #74655 parse int and float distort data
Submitted: 2017-05-26 09:47 UTC Modified: 2017-05-26 10:04 UTC
From: an dot nguyen-hoai at lazada dot com Assigned:
Status: Not a bug Package: Math related
PHP Version: 7.0.19 OS: Docker Ubuntu
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please !
Your email address:
MUST BE VALID
Solve the problem:
20 - 10 = ?
Subscribe to this entry?

 
 [2017-05-26 09:47 UTC] 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

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-05-26 10:04 UTC] danack@php.net
-Status: Open +Status: Not a bug
 [2017-05-26 10:04 UTC] danack@php.net
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.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 13:01:28 2024 UTC