Issues (96)

src/Helper/NumberHelper.php (1 issue)

Labels
Severity
1
<?php
2
3
/**
4
 * Platine Framework
5
 *
6
 * Platine Framework is a lightweight, high-performance, simple and elegant
7
 * PHP Web framework
8
 *
9
 * This content is released under the MIT License (MIT)
10
 *
11
 * Copyright (c) 2020 Platine Framework
12
 *
13
 * Permission is hereby granted, free of charge, to any person obtaining a copy
14
 * of this software and associated documentation files (the "Software"), to deal
15
 * in the Software without restriction, including without limitation the rights
16
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
 * copies of the Software, and to permit persons to whom the Software is
18
 * furnished to do so, subject to the following conditions:
19
 *
20
 * The above copyright notice and this permission notice shall be included in all
21
 * copies or substantial portions of the Software.
22
 *
23
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
 * SOFTWARE.
30
 */
31
32
declare(strict_types=1);
33
34
namespace Platine\Framework\Helper;
35
36
/**
37
 * @class NumberHelper
38
 * @package Platine\Framework\Helper
39
 */
40
class NumberHelper
41
{
42
    /**
43
     * Float comparison delta value
44
     */
45
    public const FLOAT_DELTA = 0.004;
46
47
    /**
48
     * Float can't be compared using equality this function is useful
49
     * to compare two float value using epsilon
50
     * @param float $a
51
     * @param float $b
52
     * @return bool
53
     */
54
    public static function isEqual(float $a, float $b): bool
55
    {
56
        return abs($a - $b) < self::FLOAT_DELTA;
57
    }
58
59
    /**
60
     * If two float is not equal
61
     * @param float $a
62
     * @param float $b
63
     * @return bool
64
     */
65
    public static function isNotEqual(float $a, float $b): bool
66
    {
67
        return self::isEqual($a, $b) === false;
68
    }
69
70
    /**
71
     * If first parameter is less than the second one
72
     * @param float $a
73
     * @param float $b
74
     * @return bool
75
     */
76
    public static function isLessThan(float $a, float $b): bool
77
    {
78
        return ($b - $a) > self::FLOAT_DELTA;
79
    }
80
81
    /**
82
     * If first parameter is greater than the second one
83
     * @param float $a
84
     * @param float $b
85
     * @return bool
86
     */
87
    public static function isGreaterThan(float $a, float $b): bool
88
    {
89
        return ($a - $b) > self::FLOAT_DELTA;
90
    }
91
92
    /**
93
     * Return the given float number to string
94
     * in order to fix some issue in some OS "." is replaced by ","
95
     * @param float|int $amount
96
     * @return string
97
     */
98
    public static function numberToString(float|int $amount): string
99
    {
100
        $value = (string) $amount;
101
        if (stripos($value, 'e') !== false) {
102
            // PHP use scientific notation if decimal has 4 zeros
103
            // after dot. so use number format instead of
104
            $value = self::floatToString($amount);
105
        }
106
107
        return str_replace(',', '.', $value);
108
    }
109
110
    /**
111
     * Convert float number to string without scientific notation
112
     * @param float $amount
113
     * @return string
114
     */
115
    public static function floatToString(float $amount): string
116
    {
117
        $value = (string) $amount;
118
        if (strpos($value, 'e') === false && strpos($value, 'E') === false) {
119
            return $value;
120
        }
121
        list($base, $decimal) = explode('E', str_replace('e', 'E', $value));
122
        $exponent = (int)$decimal;
123
        if ($exponent >= 0) {
124
            // Positive exponent: add zeros to the right
125
            $parts = explode('.', $base);
126
            $integerPart = $parts[0];
127
            $decimalPart = $parts[1] ?? '';
128
129
            $numToMove = min($exponent, strlen($decimalPart));
130
            $integerPart .= substr($decimalPart, 0, $numToMove);
131
            $newDecimalPart = substr($decimalPart, $numToMove);
132
133
            $integerPart .= str_repeat('0', $exponent - $numToMove);
134
135
            return $newDecimalPart === '' ? $integerPart : sprintf(
136
                '%s.%s',
137
                $integerPart,
138
                $newDecimalPart
139
            );
140
        }
141
        // Negative exponent: add zeros to the left
142
        $absExponent = abs($exponent);
143
        $parts = explode('.', $base);
144
        $integerPart = $parts[0];
145
        $decimalPart = $parts[1] ?? '';
146
147
        $fullNumber = $integerPart . $decimalPart;
148
        $numZeros = $absExponent - strlen($integerPart);
149
        // @codeCoverageIgnoreStart
150
        if ($numZeros < 0) { // Exponent is smaller than integer part length
151
            $insertPoint = strlen($integerPart) + $exponent; // Exponent is negative
152
            return sprintf(
153
                '%s.%s',
154
                substr($fullNumber, 0, $insertPoint),
155
                substr($fullNumber, $insertPoint)
156
            );
157
        }
158
        // @codeCoverageIgnoreEnd
159
160
        return sprintf(
161
            '0.%s%s',
162
            str_repeat('0', $numZeros),
0 ignored issues
show
$numZeros of type double is incompatible with the type integer expected by parameter $times of str_repeat(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

162
            str_repeat('0', /** @scrutinizer ignore-type */ $numZeros),
Loading history...
163
            $fullNumber
164
        );
165
    }
166
}
167