|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace DataValues\Tests; |
|
4
|
|
|
|
|
5
|
|
|
use DataValues\DecimalMath; |
|
6
|
|
|
use DataValues\DecimalValue; |
|
7
|
|
|
|
|
8
|
|
|
/** |
|
9
|
|
|
* @covers \DataValues\DecimalMath |
|
10
|
|
|
* |
|
11
|
|
|
* @group DataValue |
|
12
|
|
|
* @group DataValueExtensions |
|
13
|
|
|
* |
|
14
|
|
|
* @license GPL-2.0+ |
|
15
|
|
|
* @author Daniel Kinzler |
|
16
|
|
|
*/ |
|
17
|
|
|
class DecimalMathTest extends \PHPUnit_Framework_TestCase { |
|
18
|
|
|
|
|
19
|
|
|
public function setUp() { |
|
20
|
|
|
if ( !\extension_loaded( 'bcmath' ) ) { |
|
21
|
|
|
$this->markTestSkipped( 'bcmath extension not loaded' ); |
|
22
|
|
|
} |
|
23
|
|
|
} |
|
24
|
|
|
|
|
25
|
|
|
/** |
|
26
|
|
|
* @dataProvider bumpProvider |
|
27
|
|
|
*/ |
|
28
|
|
|
public function testBump( DecimalValue $value, $expected ) { |
|
29
|
|
|
$math = new DecimalMath(); |
|
30
|
|
|
$actual = $math->bump( $value ); |
|
31
|
|
|
$this->assertSame( $expected, $actual->getValue() ); |
|
32
|
|
|
} |
|
33
|
|
|
|
|
34
|
|
|
public function bumpProvider() { |
|
35
|
|
|
return [ |
|
36
|
|
|
[ new DecimalValue( '+0' ), '+1' ], |
|
37
|
|
|
[ new DecimalValue( '-0' ), '+1' ], |
|
38
|
|
|
[ new DecimalValue( '+0.0' ), '+0.1' ], |
|
39
|
|
|
[ new DecimalValue( '-0.0' ), '+0.1' ], |
|
40
|
|
|
[ new DecimalValue( '+1' ), '+2' ], |
|
41
|
|
|
[ new DecimalValue( '-1' ), '-2' ], |
|
42
|
|
|
[ new DecimalValue( '+10' ), '+11' ], |
|
43
|
|
|
[ new DecimalValue( '-10' ), '-11' ], |
|
44
|
|
|
[ new DecimalValue( '+9' ), '+10' ], |
|
45
|
|
|
[ new DecimalValue( '-9' ), '-10' ], |
|
46
|
|
|
[ new DecimalValue( '+0.01' ), '+0.02' ], |
|
47
|
|
|
[ new DecimalValue( '-0.01' ), '-0.02' ], |
|
48
|
|
|
[ new DecimalValue( '+0.09' ), '+0.10' ], |
|
49
|
|
|
[ new DecimalValue( '-0.09' ), '-0.10' ], |
|
50
|
|
|
[ new DecimalValue( '+0.9' ), '+1.0' ], |
|
51
|
|
|
[ new DecimalValue( '-0.9' ), '-1.0' ], |
|
52
|
|
|
]; |
|
53
|
|
|
} |
|
54
|
|
|
|
|
55
|
|
|
/** |
|
56
|
|
|
* @dataProvider slumpProvider |
|
57
|
|
|
*/ |
|
58
|
|
|
public function testSlump( DecimalValue $value, $expected ) { |
|
59
|
|
|
$math = new DecimalMath(); |
|
60
|
|
|
$actual = $math->slump( $value ); |
|
61
|
|
|
$this->assertSame( $expected, $actual->getValue() ); |
|
62
|
|
|
} |
|
63
|
|
|
|
|
64
|
|
|
public function slumpProvider() { |
|
65
|
|
|
return [ |
|
66
|
|
|
[ new DecimalValue( '+0' ), '-1' ], |
|
67
|
|
|
[ new DecimalValue( '-0' ), '-1' ], |
|
68
|
|
|
[ new DecimalValue( '+0.0' ), '-0.1' ], |
|
69
|
|
|
[ new DecimalValue( '-0.0' ), '-0.1' ], |
|
70
|
|
|
[ new DecimalValue( '+0.00' ), '-0.01' ], |
|
71
|
|
|
[ new DecimalValue( '-0.00' ), '-0.01' ], |
|
72
|
|
|
[ new DecimalValue( '+1' ), '+0' ], |
|
73
|
|
|
[ new DecimalValue( '-1' ), '+0' ], |
|
74
|
|
|
[ new DecimalValue( '+1.0' ), '+0.9' ], |
|
75
|
|
|
[ new DecimalValue( '-1.0' ), '-0.9' ], |
|
76
|
|
|
[ new DecimalValue( '+0.1' ), '+0.0' ], |
|
77
|
|
|
[ new DecimalValue( '-0.1' ), '+0.0' ], // zero is always normalized to be positive |
|
78
|
|
|
[ new DecimalValue( '+0.01' ), '+0.00' ], |
|
79
|
|
|
[ new DecimalValue( '-0.01' ), '+0.00' ], // zero is always normalized to be positive |
|
80
|
|
|
[ new DecimalValue( '+12' ), '+11' ], |
|
81
|
|
|
[ new DecimalValue( '-12' ), '-11' ], |
|
82
|
|
|
[ new DecimalValue( '+10' ), '+9' ], |
|
83
|
|
|
[ new DecimalValue( '-10' ), '-9' ], |
|
84
|
|
|
[ new DecimalValue( '+100' ), '+99' ], |
|
85
|
|
|
[ new DecimalValue( '-100' ), '-99' ], |
|
86
|
|
|
[ new DecimalValue( '+0.02' ), '+0.01' ], |
|
87
|
|
|
[ new DecimalValue( '-0.02' ), '-0.01' ], |
|
88
|
|
|
[ new DecimalValue( '+0.10' ), '+0.09' ], |
|
89
|
|
|
[ new DecimalValue( '-0.10' ), '-0.09' ], |
|
90
|
|
|
]; |
|
91
|
|
|
} |
|
92
|
|
|
|
|
93
|
|
|
/** |
|
94
|
|
|
* @dataProvider productProvider |
|
95
|
|
|
*/ |
|
96
|
|
|
public function testProduct( DecimalValue $a, DecimalValue $b, $value ) { |
|
97
|
|
|
// FIXME: This should set $useBC to false (bcmath is tested below) |
|
98
|
|
|
$math = new DecimalMath( /* $useBC */ true ); |
|
99
|
|
|
|
|
100
|
|
|
$actual = $math->product( $a, $b ); |
|
101
|
|
|
$this->assertSame( $value, $actual->getValue() ); |
|
102
|
|
|
|
|
103
|
|
|
$actual = $math->product( $b, $a ); |
|
104
|
|
|
$this->assertSame( $value, $actual->getValue() ); |
|
105
|
|
|
} |
|
106
|
|
|
|
|
107
|
|
|
public function productProvider() { |
|
108
|
|
|
return [ |
|
109
|
|
|
[ new DecimalValue( '+0' ), new DecimalValue( '+0' ), '+0' ], |
|
110
|
|
|
[ new DecimalValue( '+0' ), new DecimalValue( '+1' ), '+0' ], |
|
111
|
|
|
[ new DecimalValue( '+0' ), new DecimalValue( '+2' ), '+0' ], |
|
112
|
|
|
|
|
113
|
|
|
[ new DecimalValue( '+1' ), new DecimalValue( '+0' ), '+0' ], |
|
114
|
|
|
[ new DecimalValue( '+1' ), new DecimalValue( '+1' ), '+1' ], |
|
115
|
|
|
[ new DecimalValue( '+1' ), new DecimalValue( '+2' ), '+2' ], |
|
116
|
|
|
|
|
117
|
|
|
[ new DecimalValue( '+2' ), new DecimalValue( '+0' ), '+0' ], |
|
118
|
|
|
[ new DecimalValue( '+2' ), new DecimalValue( '+1' ), '+2' ], |
|
119
|
|
|
[ new DecimalValue( '+2' ), new DecimalValue( '+2' ), '+4' ], |
|
120
|
|
|
|
|
121
|
|
|
[ new DecimalValue( '+0.5' ), new DecimalValue( '+0' ), '+0.0' ], |
|
122
|
|
|
[ new DecimalValue( '+0.5' ), new DecimalValue( '+1' ), '+0.5' ], |
|
123
|
|
|
[ new DecimalValue( '+0.5' ), new DecimalValue( '+2' ), '+1.0' ], |
|
124
|
|
|
]; |
|
125
|
|
|
} |
|
126
|
|
|
|
|
127
|
|
|
/** |
|
128
|
|
|
* @dataProvider productWithBCProvider |
|
129
|
|
|
*/ |
|
130
|
|
|
public function testProductWithBC( DecimalValue $a, DecimalValue $b, $value ) { |
|
131
|
|
|
$math = new DecimalMath(); |
|
132
|
|
|
|
|
133
|
|
|
$actual = $math->product( $a, $b ); |
|
134
|
|
|
$this->assertSame( $value, $actual->getValue() ); |
|
135
|
|
|
|
|
136
|
|
|
$actual = $math->product( $b, $a ); |
|
137
|
|
|
$this->assertSame( $value, $actual->getValue() ); |
|
138
|
|
|
} |
|
139
|
|
|
|
|
140
|
|
|
public function productWithBCProvider() { |
|
141
|
|
|
return [ |
|
142
|
|
|
[ new DecimalValue( '+0.1' ), new DecimalValue( '+0.1' ), '+0.01' ], |
|
143
|
|
|
[ new DecimalValue( '-5000000' ), new DecimalValue( '-0.1' ), '+500000.0' ], |
|
144
|
|
|
]; |
|
145
|
|
|
} |
|
146
|
|
|
|
|
147
|
|
|
/** |
|
148
|
|
|
* @dataProvider productLengthOverrunProvider |
|
149
|
|
|
*/ |
|
150
|
|
|
public function testProductLengthOverrun( DecimalValue $a, DecimalValue $b ) { |
|
151
|
|
|
$math = new DecimalMath(); |
|
152
|
|
|
$actual = $math->product( $a, $b ); |
|
153
|
|
|
|
|
154
|
|
|
$this->assertSame( 127, strlen( $actual->getValue() ) ); |
|
155
|
|
|
} |
|
156
|
|
|
|
|
157
|
|
|
public function productLengthOverrunProvider() { |
|
158
|
|
|
return [ |
|
159
|
|
|
[ |
|
160
|
|
|
new DecimalValue( '+0.' . str_repeat( '3', 124 ) ), |
|
161
|
|
|
new DecimalValue( '+0.' . str_repeat( '6', 124 ) ) |
|
162
|
|
|
], |
|
163
|
|
|
[ |
|
164
|
|
|
new DecimalValue( '+' . str_repeat( '9', 126 ) ), |
|
165
|
|
|
new DecimalValue( '+0.' . str_repeat( '9', 124 ) ) |
|
166
|
|
|
], |
|
167
|
|
|
]; |
|
168
|
|
|
} |
|
169
|
|
|
|
|
170
|
|
|
/** |
|
171
|
|
|
* @dataProvider sumProvider |
|
172
|
|
|
*/ |
|
173
|
|
|
public function testSum( DecimalValue $a, DecimalValue $b, $value ) { |
|
174
|
|
|
$math = new DecimalMath(); |
|
175
|
|
|
|
|
176
|
|
|
$actual = $math->sum( $a, $b ); |
|
177
|
|
|
$this->assertSame( $value, $actual->getValue() ); |
|
178
|
|
|
|
|
179
|
|
|
$actual = $math->sum( $b, $a ); |
|
180
|
|
|
$this->assertSame( $value, $actual->getValue() ); |
|
181
|
|
|
} |
|
182
|
|
|
|
|
183
|
|
|
public function sumProvider() { |
|
184
|
|
|
return [ |
|
185
|
|
|
[ new DecimalValue( '+0' ), new DecimalValue( '+0' ), '+0' ], |
|
186
|
|
|
[ new DecimalValue( '+0' ), new DecimalValue( '+1' ), '+1' ], |
|
187
|
|
|
[ new DecimalValue( '+0' ), new DecimalValue( '+2' ), '+2' ], |
|
188
|
|
|
|
|
189
|
|
|
[ new DecimalValue( '+2' ), new DecimalValue( '+0' ), '+2' ], |
|
190
|
|
|
[ new DecimalValue( '+2' ), new DecimalValue( '+1' ), '+3' ], |
|
191
|
|
|
[ new DecimalValue( '+2' ), new DecimalValue( '+2' ), '+4' ], |
|
192
|
|
|
|
|
193
|
|
|
[ new DecimalValue( '+0.5' ), new DecimalValue( '+0' ), '+0.5' ], |
|
194
|
|
|
[ new DecimalValue( '+0.5' ), new DecimalValue( '+0.5' ), '+1.0' ], |
|
195
|
|
|
[ new DecimalValue( '+0.5' ), new DecimalValue( '+2' ), '+2.5' ], |
|
196
|
|
|
]; |
|
197
|
|
|
} |
|
198
|
|
|
|
|
199
|
|
|
/** |
|
200
|
|
|
* @dataProvider minMaxProvider |
|
201
|
|
|
*/ |
|
202
|
|
|
public function testMin( DecimalValue $min, DecimalValue $max ) { |
|
203
|
|
|
$math = new DecimalMath(); |
|
204
|
|
|
|
|
205
|
|
|
$actual = $math->min( $min, $max ); |
|
206
|
|
|
$this->assertSame( $min->getValue(), $actual->getValue() ); |
|
207
|
|
|
|
|
208
|
|
|
$actual = $math->min( $max, $min ); |
|
209
|
|
|
$this->assertSame( $min->getValue(), $actual->getValue() ); |
|
210
|
|
|
} |
|
211
|
|
|
|
|
212
|
|
|
/** |
|
213
|
|
|
* @dataProvider minMaxProvider |
|
214
|
|
|
*/ |
|
215
|
|
|
public function testMax( DecimalValue $min, DecimalValue $max ) { |
|
216
|
|
|
$math = new DecimalMath(); |
|
217
|
|
|
|
|
218
|
|
|
$actual = $math->max( $min, $max ); |
|
219
|
|
|
$this->assertSame( $max->getValue(), $actual->getValue() ); |
|
220
|
|
|
|
|
221
|
|
|
$actual = $math->max( $max, $min ); |
|
222
|
|
|
$this->assertSame( $max->getValue(), $actual->getValue() ); |
|
223
|
|
|
} |
|
224
|
|
|
|
|
225
|
|
|
public function minMaxProvider() { |
|
226
|
|
|
return [ |
|
227
|
|
|
[ new DecimalValue( '+0' ), new DecimalValue( '+0' ) ], |
|
228
|
|
|
[ new DecimalValue( '+1' ), new DecimalValue( '+1' ) ], |
|
229
|
|
|
[ new DecimalValue( '-0.2' ), new DecimalValue( '-0.2' ) ], |
|
230
|
|
|
|
|
231
|
|
|
[ new DecimalValue( '-2' ), new DecimalValue( '+1' ) ], |
|
232
|
|
|
[ new DecimalValue( '+0.33333' ), new DecimalValue( '+1' ) ], |
|
233
|
|
|
]; |
|
234
|
|
|
} |
|
235
|
|
|
|
|
236
|
|
|
/** |
|
237
|
|
|
* @dataProvider roundToDigitProvider |
|
238
|
|
|
*/ |
|
239
|
|
|
public function testRoundToDigit( DecimalValue $value, $digits, $expected ) { |
|
240
|
|
|
$math = new DecimalMath(); |
|
241
|
|
|
|
|
242
|
|
|
$actual = $math->roundToDigit( $value, $digits ); |
|
243
|
|
|
$this->assertSame( $expected, $actual->getValue() ); |
|
244
|
|
|
} |
|
245
|
|
|
|
|
246
|
|
|
public function roundToDigitProvider() { |
|
247
|
|
|
$argLists = []; |
|
248
|
|
|
|
|
249
|
|
|
//NOTE: Rounding is applied using the "round half away from zero" logic. |
|
250
|
|
|
|
|
251
|
|
|
$argLists[] = [ new DecimalValue( '-2' ), 0, '+0' ]; // no digits left |
|
252
|
|
|
|
|
253
|
|
|
$argLists[] = [ new DecimalValue( '+0' ), 1, '+0' ]; |
|
254
|
|
|
$argLists[] = [ new DecimalValue( '+0' ), 2, '+0' ]; |
|
255
|
|
|
$argLists[] = [ new DecimalValue( '+0.0' ), 1, '+0' ]; |
|
256
|
|
|
$argLists[] = [ new DecimalValue( '+0.0' ), 2, '+0' ]; |
|
257
|
|
|
$argLists[] = [ new DecimalValue( '+0.0' ), 3, '+0.0' ]; |
|
258
|
|
|
|
|
259
|
|
|
$argLists[] = [ new DecimalValue( '+1.45' ), 1, '+1' ]; |
|
260
|
|
|
$argLists[] = [ new DecimalValue( '+1.45' ), 3, '+1.5' ]; |
|
261
|
|
|
$argLists[] = [ new DecimalValue( '+1.45' ), 4, '+1.45' ]; |
|
262
|
|
|
|
|
263
|
|
|
$argLists[] = [ new DecimalValue( '-1.45' ), 1, '-1' ]; |
|
264
|
|
|
$argLists[] = [ new DecimalValue( '-1.45' ), 3, '-1.5' ]; |
|
265
|
|
|
$argLists[] = [ new DecimalValue( '-1.45' ), 4, '-1.45' ]; |
|
266
|
|
|
|
|
267
|
|
|
$argLists[] = [ new DecimalValue( '+9.99' ), 1, '+10' ]; |
|
268
|
|
|
$argLists[] = [ new DecimalValue( '+9.99' ), 3, '+10.0' ]; |
|
269
|
|
|
$argLists[] = [ new DecimalValue( '+9.99' ), 4, '+9.99' ]; |
|
270
|
|
|
|
|
271
|
|
|
$argLists[] = [ new DecimalValue( '+135.7' ), 1, '+100' ]; |
|
272
|
|
|
$argLists[] = [ new DecimalValue( '+135.7' ), 3, '+136' ]; |
|
273
|
|
|
$argLists[] = [ new DecimalValue( '+135.7' ), 5, '+135.7' ]; |
|
274
|
|
|
|
|
275
|
|
|
$argLists[] = [ new DecimalValue( '-2' ), 1, '-2' ]; |
|
276
|
|
|
$argLists[] = [ new DecimalValue( '-2' ), 2, '-2' ]; |
|
277
|
|
|
|
|
278
|
|
|
$argLists[] = [ new DecimalValue( '+23' ), 1, '+20' ]; |
|
279
|
|
|
$argLists[] = [ new DecimalValue( '+23' ), 2, '+23' ]; |
|
280
|
|
|
$argLists[] = [ new DecimalValue( '+23' ), 3, '+23' ]; |
|
281
|
|
|
$argLists[] = [ new DecimalValue( '+23' ), 4, '+23' ]; |
|
282
|
|
|
|
|
283
|
|
|
$argLists[] = [ new DecimalValue( '-234' ), 1, '-200' ]; |
|
284
|
|
|
$argLists[] = [ new DecimalValue( '-234' ), 2, '-230' ]; |
|
285
|
|
|
$argLists[] = [ new DecimalValue( '-234' ), 3, '-234' ]; |
|
286
|
|
|
|
|
287
|
|
|
$argLists[] = [ new DecimalValue( '-2.0' ), 1, '-2' ]; |
|
288
|
|
|
$argLists[] = [ new DecimalValue( '-2.0' ), 2, '-2' ]; // not padded (can't end with decimal point) |
|
289
|
|
|
$argLists[] = [ new DecimalValue( '-2.0' ), 3, '-2.0' ]; |
|
290
|
|
|
$argLists[] = [ new DecimalValue( '-2.0' ), 4, '-2.0' ]; // no extra digits |
|
291
|
|
|
|
|
292
|
|
|
$argLists[] = [ new DecimalValue( '-2.000' ), 1, '-2' ]; |
|
293
|
|
|
$argLists[] = [ new DecimalValue( '-2.000' ), 2, '-2' ]; |
|
294
|
|
|
$argLists[] = [ new DecimalValue( '-2.000' ), 3, '-2.0' ]; |
|
295
|
|
|
$argLists[] = [ new DecimalValue( '-2.000' ), 4, '-2.00' ]; |
|
296
|
|
|
|
|
297
|
|
|
$argLists[] = [ new DecimalValue( '+2.5' ), 1, '+3' ]; // rounded up |
|
298
|
|
|
$argLists[] = [ new DecimalValue( '+2.5' ), 2, '+3' ]; |
|
299
|
|
|
$argLists[] = [ new DecimalValue( '+2.5' ), 3, '+2.5' ]; |
|
300
|
|
|
$argLists[] = [ new DecimalValue( '+2.5' ), 4, '+2.5' ]; |
|
301
|
|
|
|
|
302
|
|
|
$argLists[] = [ new DecimalValue( '+2.05' ), 1, '+2' ]; |
|
303
|
|
|
$argLists[] = [ new DecimalValue( '+2.05' ), 2, '+2' ]; |
|
304
|
|
|
$argLists[] = [ new DecimalValue( '+2.05' ), 3, '+2.1' ]; // rounded up |
|
305
|
|
|
$argLists[] = [ new DecimalValue( '+2.05' ), 4, '+2.05' ]; |
|
306
|
|
|
|
|
307
|
|
|
$argLists[] = [ new DecimalValue( '-23.05' ), 1, '-20' ]; |
|
308
|
|
|
$argLists[] = [ new DecimalValue( '-23.05' ), 2, '-23' ]; |
|
309
|
|
|
$argLists[] = [ new DecimalValue( '-23.05' ), 3, '-23' ]; // not padded (can't end with decimal point) |
|
310
|
|
|
$argLists[] = [ new DecimalValue( '-23.05' ), 4, '-23.1' ]; // rounded down |
|
311
|
|
|
$argLists[] = [ new DecimalValue( '-23.05' ), 5, '-23.05' ]; |
|
312
|
|
|
|
|
313
|
|
|
$argLists[] = [ new DecimalValue( '+9.33' ), 1, '+9' ]; // no rounding |
|
314
|
|
|
$argLists[] = [ new DecimalValue( '+9.87' ), 1, '+10' ]; // rounding ripples up |
|
315
|
|
|
$argLists[] = [ new DecimalValue( '+9.87' ), 3, '+9.9' ]; // rounding ripples up |
|
316
|
|
|
$argLists[] = [ new DecimalValue( '+99' ), 1, '+100' ]; // rounding ripples up |
|
317
|
|
|
$argLists[] = [ new DecimalValue( '+99' ), 2, '+99' ]; // rounding ripples up |
|
318
|
|
|
|
|
319
|
|
|
$argLists[] = [ new DecimalValue( '-9.33' ), 1, '-9' ]; // no rounding |
|
320
|
|
|
$argLists[] = [ new DecimalValue( '-9.87' ), 1, '-10' ]; // rounding ripples down |
|
321
|
|
|
$argLists[] = [ new DecimalValue( '-9.87' ), 3, '-9.9' ]; // rounding ripples down |
|
322
|
|
|
$argLists[] = [ new DecimalValue( '-99' ), 1, '-100' ]; // rounding ripples down |
|
323
|
|
|
$argLists[] = [ new DecimalValue( '-99' ), 2, '-99' ]; // rounding ripples down |
|
324
|
|
|
|
|
325
|
|
|
return $argLists; |
|
326
|
|
|
} |
|
327
|
|
|
|
|
328
|
|
|
/** |
|
329
|
|
|
* @dataProvider getPositionForExponentProvider |
|
330
|
|
|
*/ |
|
331
|
|
|
public function testGetPositionForExponent( $exponent, DecimalValue $decimal, $expected ) { |
|
332
|
|
|
$math = new DecimalMath(); |
|
333
|
|
|
|
|
334
|
|
|
$actual = $math->getPositionForExponent( $exponent, $decimal ); |
|
335
|
|
|
$this->assertSame( $expected, $actual ); |
|
336
|
|
|
} |
|
337
|
|
|
|
|
338
|
|
|
public function getPositionForExponentProvider() { |
|
339
|
|
|
$argLists = []; |
|
340
|
|
|
|
|
341
|
|
|
$argLists[] = [ 0, new DecimalValue( '+0' ), 1 ]; |
|
342
|
|
|
$argLists[] = [ 1, new DecimalValue( '+10.25' ), 1 ]; |
|
343
|
|
|
$argLists[] = [ 1, new DecimalValue( '-100.25' ), 2 ]; |
|
344
|
|
|
$argLists[] = [ 2, new DecimalValue( '+100.25' ), 1 ]; |
|
345
|
|
|
$argLists[] = [ -2, new DecimalValue( '+0.234' ), 4 ]; |
|
346
|
|
|
$argLists[] = [ -2, new DecimalValue( '+11.234' ), 5 ]; |
|
347
|
|
|
|
|
348
|
|
|
return $argLists; |
|
349
|
|
|
} |
|
350
|
|
|
|
|
351
|
|
|
/** |
|
352
|
|
|
* @dataProvider roundToExponentProvider |
|
353
|
|
|
*/ |
|
354
|
|
|
public function testRoundToExponent( DecimalValue $value, $digits, $expected ) { |
|
355
|
|
|
$math = new DecimalMath(); |
|
356
|
|
|
|
|
357
|
|
|
$actual = $math->roundToExponent( $value, $digits ); |
|
358
|
|
|
$this->assertSame( $expected, $actual->getValue() ); |
|
359
|
|
|
} |
|
360
|
|
|
|
|
361
|
|
|
public function roundToExponentProvider() { |
|
362
|
|
|
$argLists = []; |
|
363
|
|
|
|
|
364
|
|
|
//NOTE: Rounding is applied using the "round half away from zero" logic. |
|
365
|
|
|
|
|
366
|
|
|
$argLists[] = [ new DecimalValue( '+0' ), 0, '+0' ]; |
|
367
|
|
|
$argLists[] = [ new DecimalValue( '+0' ), 1, '+0' ]; |
|
368
|
|
|
$argLists[] = [ new DecimalValue( '+0.0' ), 0, '+0' ]; |
|
369
|
|
|
$argLists[] = [ new DecimalValue( '+0.0' ), 2, '+0' ]; |
|
370
|
|
|
$argLists[] = [ new DecimalValue( '+0.0' ), -5, '+0.0' ]; // no extra digits |
|
371
|
|
|
|
|
372
|
|
|
$argLists[] = [ new DecimalValue( '+1.45' ), 0, '+1' ]; |
|
373
|
|
|
$argLists[] = [ new DecimalValue( '+1.45' ), 2, '+0' ]; |
|
374
|
|
|
$argLists[] = [ new DecimalValue( '+1.45' ), -5, '+1.45' ]; |
|
375
|
|
|
|
|
376
|
|
|
$argLists[] = [ new DecimalValue( '+99.99' ), 0, '+100' ]; |
|
377
|
|
|
$argLists[] = [ new DecimalValue( '+99.99' ), 2, '+0' ]; |
|
378
|
|
|
$argLists[] = [ new DecimalValue( '+99.99' ), -1, '+100.0' ]; |
|
379
|
|
|
$argLists[] = [ new DecimalValue( '+99.99' ), -5, '+99.99' ]; |
|
380
|
|
|
|
|
381
|
|
|
$argLists[] = [ new DecimalValue( '-2' ), 0, '-2' ]; |
|
382
|
|
|
$argLists[] = [ new DecimalValue( '-2' ), -1, '-2' ]; |
|
383
|
|
|
$argLists[] = [ new DecimalValue( '-2' ), 1, '+0' ]; |
|
384
|
|
|
|
|
385
|
|
|
$argLists[] = [ new DecimalValue( '+23' ), 0, '+23' ]; |
|
386
|
|
|
$argLists[] = [ new DecimalValue( '+23' ), 1, '+20' ]; |
|
387
|
|
|
$argLists[] = [ new DecimalValue( '+23' ), 2, '+0' ]; |
|
388
|
|
|
|
|
389
|
|
|
$argLists[] = [ new DecimalValue( '-234' ), 2, '-200' ]; |
|
390
|
|
|
$argLists[] = [ new DecimalValue( '-234' ), 1, '-230' ]; |
|
391
|
|
|
$argLists[] = [ new DecimalValue( '-234' ), 0, '-234' ]; |
|
392
|
|
|
|
|
393
|
|
|
$argLists[] = [ new DecimalValue( '-2.0' ), 0, '-2' ]; |
|
394
|
|
|
$argLists[] = [ new DecimalValue( '-2.0' ), -1, '-2.0' ]; |
|
395
|
|
|
$argLists[] = [ new DecimalValue( '-2.0' ), -2, '-2.0' ]; // no extra digits |
|
396
|
|
|
|
|
397
|
|
|
$argLists[] = [ new DecimalValue( '-2.000' ), 0, '-2' ]; |
|
398
|
|
|
$argLists[] = [ new DecimalValue( '-2.000' ), -1, '-2.0' ]; |
|
399
|
|
|
$argLists[] = [ new DecimalValue( '-2.000' ), -2, '-2.00' ]; |
|
400
|
|
|
|
|
401
|
|
|
$argLists[] = [ new DecimalValue( '+2.5' ), 0, '+3' ]; // rounded up |
|
402
|
|
|
$argLists[] = [ new DecimalValue( '+2.5' ), -1, '+2.5' ]; |
|
403
|
|
|
$argLists[] = [ new DecimalValue( '+2.5' ), -2, '+2.5' ]; // no extra digits |
|
404
|
|
|
|
|
405
|
|
|
$argLists[] = [ new DecimalValue( '+2.05' ), 0, '+2' ]; |
|
406
|
|
|
$argLists[] = [ new DecimalValue( '+2.05' ), -1, '+2.1' ]; // rounded up |
|
407
|
|
|
$argLists[] = [ new DecimalValue( '+2.05' ), -2, '+2.05' ]; |
|
408
|
|
|
|
|
409
|
|
|
$argLists[] = [ new DecimalValue( '-23.05' ), 1, '-20' ]; |
|
410
|
|
|
$argLists[] = [ new DecimalValue( '-23.05' ), 0, '-23' ]; |
|
411
|
|
|
|
|
412
|
|
|
$argLists[] = [ new DecimalValue( '-23.05' ), -1, '-23.1' ]; // rounded down |
|
413
|
|
|
$argLists[] = [ new DecimalValue( '-23.05' ), -2, '-23.05' ]; |
|
414
|
|
|
|
|
415
|
|
|
$argLists[] = [ new DecimalValue( '+9.33' ), 0, '+9' ]; // no rounding |
|
416
|
|
|
$argLists[] = [ new DecimalValue( '+9.87' ), 0, '+10' ]; // rounding ripples up |
|
417
|
|
|
$argLists[] = [ new DecimalValue( '+9.87' ), -1, '+9.9' ]; // rounding ripples up |
|
418
|
|
|
$argLists[] = [ new DecimalValue( '+99' ), 1, '+100' ]; // rounding ripples up |
|
419
|
|
|
$argLists[] = [ new DecimalValue( '+99' ), 0, '+99' ]; // rounding ripples up |
|
420
|
|
|
|
|
421
|
|
|
$argLists[] = [ new DecimalValue( '-9.33' ), 0, '-9' ]; // no rounding |
|
422
|
|
|
$argLists[] = [ new DecimalValue( '-9.87' ), 0, '-10' ]; // rounding ripples down |
|
423
|
|
|
$argLists[] = [ new DecimalValue( '-9.87' ), -1, '-9.9' ]; // rounding ripples down |
|
424
|
|
|
$argLists[] = [ new DecimalValue( '-99' ), 1, '-100' ]; // rounding ripples down |
|
425
|
|
|
$argLists[] = [ new DecimalValue( '-99' ), 0, '-99' ]; // rounding ripples down |
|
426
|
|
|
|
|
427
|
|
|
return $argLists; |
|
428
|
|
|
} |
|
429
|
|
|
|
|
430
|
|
|
/** |
|
431
|
|
|
* @dataProvider shiftProvider |
|
432
|
|
|
*/ |
|
433
|
|
|
public function testShift( DecimalValue $value, $exponent, $expected ) { |
|
434
|
|
|
$math = new DecimalMath(); |
|
435
|
|
|
|
|
436
|
|
|
$actual = $math->shift( $value, $exponent ); |
|
437
|
|
|
$this->assertSame( $expected, $actual->getValue() ); |
|
438
|
|
|
} |
|
439
|
|
|
|
|
440
|
|
|
public function shiftProvider() { |
|
441
|
|
|
$argLists = []; |
|
442
|
|
|
|
|
443
|
|
|
$argLists[] = [ new DecimalValue( '+0' ), 0, '+0' ]; |
|
444
|
|
|
$argLists[] = [ new DecimalValue( '+0' ), 1, '+0' ]; |
|
445
|
|
|
$argLists[] = [ new DecimalValue( '+0' ), 2, '+0' ]; |
|
446
|
|
|
$argLists[] = [ new DecimalValue( '+0' ), -1, '+0.0' ]; |
|
447
|
|
|
$argLists[] = [ new DecimalValue( '+0' ), -2, '+0.00' ]; |
|
448
|
|
|
|
|
449
|
|
|
$argLists[] = [ new DecimalValue( '+0.0' ), 0, '+0.0' ]; |
|
450
|
|
|
$argLists[] = [ new DecimalValue( '+0.0' ), 1, '+0' ]; |
|
451
|
|
|
$argLists[] = [ new DecimalValue( '+0.0' ), 2, '+0' ]; |
|
452
|
|
|
$argLists[] = [ new DecimalValue( '+0.0' ), -1, '+0.00' ]; |
|
453
|
|
|
$argLists[] = [ new DecimalValue( '+0.0' ), -2, '+0.000' ]; |
|
454
|
|
|
|
|
455
|
|
|
$argLists[] = [ new DecimalValue( '-125' ), 0, '-125' ]; |
|
456
|
|
|
$argLists[] = [ new DecimalValue( '-125' ), 1, '-1250' ]; |
|
457
|
|
|
$argLists[] = [ new DecimalValue( '-125' ), 2, '-12500' ]; |
|
458
|
|
|
$argLists[] = [ new DecimalValue( '-125' ), -1, '-12.5' ]; |
|
459
|
|
|
$argLists[] = [ new DecimalValue( '-125' ), -2, '-1.25' ]; |
|
460
|
|
|
$argLists[] = [ new DecimalValue( '-125' ), -3, '-0.125' ]; |
|
461
|
|
|
$argLists[] = [ new DecimalValue( '-125' ), -4, '-0.0125' ]; |
|
462
|
|
|
|
|
463
|
|
|
$argLists[] = [ new DecimalValue( '-2.5' ), 0, '-2.5' ]; |
|
464
|
|
|
$argLists[] = [ new DecimalValue( '-2.5' ), 1, '-25' ]; |
|
465
|
|
|
$argLists[] = [ new DecimalValue( '-2.5' ), 2, '-250' ]; |
|
466
|
|
|
$argLists[] = [ new DecimalValue( '-2.5' ), -1, '-0.25' ]; |
|
467
|
|
|
$argLists[] = [ new DecimalValue( '-2.5' ), -2, '-0.025' ]; |
|
468
|
|
|
$argLists[] = [ new DecimalValue( '-2.5' ), -3, '-0.0025' ]; |
|
469
|
|
|
|
|
470
|
|
|
$argLists[] = [ new DecimalValue( '+5' ), -4, '+0.0005' ]; |
|
471
|
|
|
$argLists[] = [ new DecimalValue( '+5.0' ), -4, '+0.00050' ]; |
|
472
|
|
|
$argLists[] = [ new DecimalValue( '+5.00' ), -4, '+0.000500' ]; |
|
473
|
|
|
|
|
474
|
|
|
return $argLists; |
|
475
|
|
|
} |
|
476
|
|
|
|
|
477
|
|
|
} |
|
478
|
|
|
|