Skip to content

Commit 85629b7

Browse files
committed
More Extreme Cases
1 parent 7b478ad commit 85629b7

File tree

3 files changed

+23
-23
lines changed

3 files changed

+23
-23
lines changed

src/PhpSpreadsheet/Calculation/MathTrig/Trunc.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,11 @@ public static function evaluate(array|float|string|null $value = 0, array|int|st
5151
}
5252
$digits = (int) floor($digits);
5353
if ($digits < 0) {
54-
$power = (int) (10 ** -$digits);
55-
$result = intdiv((int) floor($value), $power) * $power;
54+
$result = (float) (substr(sprintf('%.0F', $value), 0, $digits) . str_repeat('0', -$digits));
5655

5756
return ($minusSign === '') ? $result : -$result;
5857
}
59-
$decimals = PHP_FLOAT_DIG - strlen((string) (int) $value);
58+
$decimals = (floor($value) == (int) $value) ? (PHP_FLOAT_DIG - strlen((string) (int) $value)) : $digits;
6059
$resultString = ($decimals < 0) ? sprintf('%F', $value) : sprintf('%.' . $decimals . 'F', $value);
6160
$regExp = '/([.]\\d{' . $digits . '})\\d+$/';
6261
$result = $minusSign . (preg_replace($regExp, '$1', $resultString) ?? $resultString);

tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/TruncTest.php

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -48,35 +48,35 @@ public static function providerTruncArray(): array
4848
];
4949
}
5050

51-
public function testTooMuchPrecision(): void
51+
/**
52+
* @dataProvider providerTooMuchPrecision
53+
*/
54+
public function testTooMuchPrecision(mixed $expectedResult, float|int|string $value, int $digits = 1): void
5255
{
5356
// This test is pretty screwy. Possibly shouldn't even attempt it.
5457
// At any rate, these results seem to indicate that PHP
5558
// maximum precision is PHP_FLOAT_DIG - 1 digits, not PHP_FLOAT_DIG.
5659
// If that changes, at least one of these tests will have to change.
5760
$sheet = $this->getSheet();
58-
$sheet->getCell('E1')->setValue(10.0 ** (PHP_FLOAT_DIG - 3) + 1.2);
59-
$sheet->getCell('E2')->setValue('=TRUNC(E1,1)');
61+
$sheet->getCell('E1')->setValue($value);
62+
$sheet->getCell('E2')->setValue("=TRUNC(E1,$digits)");
6063
$result = $sheet->getCell('E2')->getCalculatedValue();
61-
$expectedResult = '1' . str_repeat('0', PHP_FLOAT_DIG - 4) . '1.2';
62-
self::assertSame($expectedResult, (string) $result);
63-
64-
$sheet->getCell('F1')->setValue(10.0 ** (PHP_FLOAT_DIG - 2) + 1.2);
65-
$sheet->getCell('F2')->setValue('=TRUNC(F1,1)');
66-
$result = $sheet->getCell('F2')->getCalculatedValue();
67-
$expectedResult = '1' . str_repeat('0', PHP_FLOAT_DIG - 3) . '1';
6864
self::assertSame($expectedResult, (string) $result);
65+
}
6966

70-
$sheet->getCell('G1')->setValue(10.0 ** (PHP_FLOAT_DIG - 1) + 1.2);
71-
$sheet->getCell('G2')->setValue('=TRUNC(G1,1)');
72-
$result = $sheet->getCell('G2')->getCalculatedValue();
73-
$expectedResult = '1.0E+' . (PHP_FLOAT_DIG - 1);
74-
self::assertSame($expectedResult, (string) $result);
67+
public static function providerTooMuchPrecision(): array
68+
{
69+
$max64Plus1 = 9223372036854775808;
70+
$stringMax = (string) $max64Plus1;
7571

76-
$sheet->getCell('H1')->setValue(10.0 ** PHP_FLOAT_DIG + 1.2);
77-
$sheet->getCell('H2')->setValue('=TRUNC(H1,1)');
78-
$result = $sheet->getCell('H2')->getCalculatedValue();
79-
$expectedResult = '1.0E+' . PHP_FLOAT_DIG;
80-
self::assertSame($expectedResult, (string) $result);
72+
return [
73+
'2 digits less than PHP_FLOAT_DIG' => ['1' . str_repeat('0', PHP_FLOAT_DIG - 4) . '1.2', 10.0 ** (PHP_FLOAT_DIG - 3) + 1.2, 1],
74+
'1 digit less than PHP_FLOAT_DIG' => ['1' . str_repeat('0', PHP_FLOAT_DIG - 3) . '1', 10.0 ** (PHP_FLOAT_DIG - 2) + 1.2, 1],
75+
'PHP_FLOAT_DIG' => ['1.0E+' . (PHP_FLOAT_DIG - 1), 10.0 ** (PHP_FLOAT_DIG - 1) + 1.2, 1],
76+
'1 digit more than PHP_FLOAT_DIG' => ['1.0E+' . PHP_FLOAT_DIG, 10.0 ** PHP_FLOAT_DIG + 1.2, 1],
77+
'32bit exceed int max' => ['3123456780', 3123456789, -1],
78+
'64bit exceed int max neg decimals' => [$stringMax, $max64Plus1, -1],
79+
'64bit exceed int max pos decimals' => [$stringMax, $max64Plus1, 1],
80+
];
8181
}
8282
}

tests/data/Calculation/MathTrig/TRUNC.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,5 @@
5151
'issue4113 example 6 variant 4' => [-0.0000123, '-0.0000123, 8'],
5252
'issue4113 example 6 variant 5' => [0.000012, '1.23E-5, 6'],
5353
'issue4113 example 6 variant 6' => [-0.0000123, '-1.23E-5, 8'],
54+
'exceed 32-bit int max' => [3123456780, '3123456789, -1'],
5455
];

0 commit comments

Comments
 (0)