1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
class Round
{
use ArrayEnabled;
/**
* ROUND.
*
* Returns the result of builtin function round after validating args.
*
* @param mixed $number Should be numeric, or can be an array of numbers
* @param mixed $precision Should be int, or can be an array of numbers
*
* @return array|float|string Rounded number
* If an array of numbers is passed as the argument, then the returned result will also be an array
* with the same dimensions
*/
public static function round($number, $precision)
{
if (is_array($number) || is_array($precision)) {
return self::evaluateArrayArguments([self::class, __FUNCTION__], $number, $precision);
}
try {
$number = Helpers::validateNumericNullBool($number);
$precision = Helpers::validateNumericNullBool($precision);
} catch (Exception $e) {
return $e->getMessage();
}
return round($number, (int) $precision);
}
/**
* ROUNDUP.
*
* Rounds a number up to a specified number of decimal places
*
* @param array|float $number Number to round, or can be an array of numbers
* @param array|int $digits Number of digits to which you want to round $number, or can be an array of numbers
*
* @return array|float|string Rounded Number, or a string containing an error
* If an array of numbers is passed as the argument, then the returned result will also be an array
* with the same dimensions
*/
public static function up($number, $digits)
{
if (is_array($number) || is_array($digits)) {
return self::evaluateArrayArguments([self::class, __FUNCTION__], $number, $digits);
}
try {
$number = Helpers::validateNumericNullBool($number);
$digits = (int) Helpers::validateNumericNullSubstitution($digits, null);
} catch (Exception $e) {
return $e->getMessage();
}
if ($number == 0.0) {
return 0.0;
}
if ($number < 0.0) {
return round($number - 0.5 * 0.1 ** $digits, $digits, PHP_ROUND_HALF_DOWN);
}
return round($number + 0.5 * 0.1 ** $digits, $digits, PHP_ROUND_HALF_DOWN);
}
/**
* ROUNDDOWN.
*
* Rounds a number down to a specified number of decimal places
*
* @param array|float $number Number to round, or can be an array of numbers
* @param array|int $digits Number of digits to which you want to round $number, or can be an array of numbers
*
* @return array|float|string Rounded Number, or a string containing an error
* If an array of numbers is passed as the argument, then the returned result will also be an array
* with the same dimensions
*/
public static function down($number, $digits)
{
if (is_array($number) || is_array($digits)) {
return self::evaluateArrayArguments([self::class, __FUNCTION__], $number, $digits);
}
try {
$number = Helpers::validateNumericNullBool($number);
$digits = (int) Helpers::validateNumericNullSubstitution($digits, null);
} catch (Exception $e) {
return $e->getMessage();
}
if ($number == 0.0) {
return 0.0;
}
if ($number < 0.0) {
return round($number + 0.5 * 0.1 ** $digits, $digits, PHP_ROUND_HALF_UP);
}
return round($number - 0.5 * 0.1 ** $digits, $digits, PHP_ROUND_HALF_UP);
}
/**
* MROUND.
*
* Rounds a number to the nearest multiple of a specified value
*
* @param mixed $number Expect float. Number to round, or can be an array of numbers
* @param mixed $multiple Expect int. Multiple to which you want to round, or can be an array of numbers.
*
* @return array|float|string Rounded Number, or a string containing an error
* If an array of numbers is passed as the argument, then the returned result will also be an array
* with the same dimensions
*/
public static function multiple($number, $multiple)
{
if (is_array($number) || is_array($multiple)) {
return self::evaluateArrayArguments([self::class, __FUNCTION__], $number, $multiple);
}
try {
$number = Helpers::validateNumericNullSubstitution($number, 0);
$multiple = Helpers::validateNumericNullSubstitution($multiple, null);
} catch (Exception $e) {
return $e->getMessage();
}
if ($number == 0 || $multiple == 0) {
return 0;
}
if ((Helpers::returnSign($number)) == (Helpers::returnSign($multiple))) {
$multiplier = 1 / $multiple;
return round($number * $multiplier) / $multiplier;
}
return ExcelError::NAN();
}
/**
* EVEN.
*
* Returns number rounded up to the nearest even integer.
* You can use this function for processing items that come in twos. For example,
* a packing crate accepts rows of one or two items. The crate is full when
* the number of items, rounded up to the nearest two, matches the crate's
* capacity.
*
* Excel Function:
* EVEN(number)
*
* @param array|float $number Number to round, or can be an array of numbers
*
* @return array|float|string Rounded Number, or a string containing an error
* If an array of numbers is passed as the argument, then the returned result will also be an array
* with the same dimensions
*/
public static function even($number)
{
if (is_array($number)) {
return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $number);
}
try {
$number = Helpers::validateNumericNullBool($number);
} catch (Exception $e) {
return $e->getMessage();
}
return Helpers::getEven($number);
}
/**
* ODD.
*
* Returns number rounded up to the nearest odd integer.
*
* @param array|float $number Number to round, or can be an array of numbers
*
* @return array|float|string Rounded Number, or a string containing an error
* If an array of numbers is passed as the argument, then the returned result will also be an array
* with the same dimensions
*/
public static function odd($number)
{
if (is_array($number)) {
return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $number);
}
try {
$number = Helpers::validateNumericNullBool($number);
} catch (Exception $e) {
return $e->getMessage();
}
$significance = Helpers::returnSign($number);
if ($significance == 0) {
return 1;
}
$result = ceil($number / $significance) * $significance;
if ($result == Helpers::getEven($result)) {
$result += $significance;
}
return $result;
}
}