Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

For PHP, real unit test scenario - can be added to docs ;) #78

Open
LocalHeroPro opened this issue Nov 11, 2022 · 0 comments
Open

For PHP, real unit test scenario - can be added to docs ;) #78

LocalHeroPro opened this issue Nov 11, 2022 · 0 comments

Comments

@LocalHeroPro
Copy link

Unit test file

<?php

declare(strict_types=1);

namespace Tests\Unit;

use App\Traits\FloatComparison;
use PHPUnit\Framework\TestCase;

class FloatComparisonTest extends TestCase
{
    use FloatComparison;

    public function testV1(): void
    {
        $toCheck = (float) '1714.23';
        $items = [ // sum of that is 1714.23
            73.03,
            59.74,
            90.03,
            67.5,
            33.07,
            87.83,
            73.03,
            47.15,
            66.12,
            67.5,
            49.56,
            92.24,
            47.65,
            12.14,
            50.77,
            80.84,
            49.56,
            45.64,
            73.03,
            38.36,
            97.21,
            11.96,
            37.86,
            87.83,
            5.02,
            91.97,
            90.03,
            8.41,
            33.07,
            46.08,
        ];
        $amount = 0;

        foreach ($items as $item) {
            $amount += $item;
        }

        self::assertTrue(self::nearlyEqual($toCheck, $amount));
    }
}

Assertion file:

<?php

declare(strict_types=1);

namespace App\Traits;

trait FloatComparison
{
    /**
     * @link https://floating-point-gui.de/errors/comparison/
     *
     * @param float $a // 1714.23
     * @param float $b // 1714.23
     *
     * @param float $epsilon // 2.2204460492503E-16
     * @param float $floatMin // 2.2250738585072e-308
     * @param floatMax // 1.7976931348623157E+308
     *
     * @return bool
     */
    public static function nearlyEqual(float $a, float $b): bool
    {
        $absA = (float) abs($a); // 1714.23
        $absB = (float) abs($b); // 1714.23
        $diff = (float) abs($a - $b); // 2.2737367544323E-13

        if ($a == $b) { // shortcut, handles infinities
            return true;
        }

        if ($a == 0 || $b == 0 || ($absA + $absB < PHP_FLOAT_MIN)) {
            // a or b is zero or both are extremely close to it
            // relative error is less meaningful here
            return $diff < (PHP_FLOAT_EPSILON * PHP_FLOAT_MIN);
        }

        // use relative error
        return $diff / min(($absA + $absB), PHP_FLOAT_MAX) < PHP_FLOAT_MIN;
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant