Skip to content

Commit

Permalink
Too Many Digits
Browse files Browse the repository at this point in the history
We can't handle more digits than Php allows. Neither can Excel. Just do our best without throwing an Error.
  • Loading branch information
oleibman committed Jul 31, 2024
1 parent e39dfe3 commit 7b478ad
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 1 deletion.
7 changes: 6 additions & 1 deletion src/PhpSpreadsheet/Calculation/MathTrig/Trunc.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ class Trunc
* TRUNC.
*
* Truncates value to the number of fractional digits by number_digits.
* This will probably not be the precise result in the unlikely
* event that the number of digits to the left of the decimal
* plus the number of digits to the right exceeds PHP_FLOAT_DIG
* (or possibly that value minus 1).
* Excel is unlikely to do any better.
*
* @param array|float $value Or can be an array of values
* @param array|int $digits Or can be an array of values
Expand Down Expand Up @@ -52,7 +57,7 @@ public static function evaluate(array|float|string|null $value = 0, array|int|st
return ($minusSign === '') ? $result : -$result;
}
$decimals = PHP_FLOAT_DIG - strlen((string) (int) $value);
$resultString = sprintf('%.' . $decimals . 'F', $value);
$resultString = ($decimals < 0) ? sprintf('%F', $value) : sprintf('%.' . $decimals . 'F', $value);
$regExp = '/([.]\\d{' . $digits . '})\\d+$/';
$result = $minusSign . (preg_replace($regExp, '$1', $resultString) ?? $resultString);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,36 @@ public static function providerTruncArray(): array
'matrix' => [[[3.14, 3.141], [3.14159, 3.14159265]], '3.1415926536', '{2, 3; 5, 8}'],
];
}

public function testTooMuchPrecision(): void
{
// This test is pretty screwy. Possibly shouldn't even attempt it.
// At any rate, these results seem to indicate that PHP
// maximum precision is PHP_FLOAT_DIG - 1 digits, not PHP_FLOAT_DIG.
// If that changes, at least one of these tests will have to change.
$sheet = $this->getSheet();
$sheet->getCell('E1')->setValue(10.0 ** (PHP_FLOAT_DIG - 3) + 1.2);
$sheet->getCell('E2')->setValue('=TRUNC(E1,1)');
$result = $sheet->getCell('E2')->getCalculatedValue();
$expectedResult = '1' . str_repeat('0', PHP_FLOAT_DIG - 4) . '1.2';
self::assertSame($expectedResult, (string) $result);

$sheet->getCell('F1')->setValue(10.0 ** (PHP_FLOAT_DIG - 2) + 1.2);
$sheet->getCell('F2')->setValue('=TRUNC(F1,1)');
$result = $sheet->getCell('F2')->getCalculatedValue();
$expectedResult = '1' . str_repeat('0', PHP_FLOAT_DIG - 3) . '1';
self::assertSame($expectedResult, (string) $result);

$sheet->getCell('G1')->setValue(10.0 ** (PHP_FLOAT_DIG - 1) + 1.2);
$sheet->getCell('G2')->setValue('=TRUNC(G1,1)');
$result = $sheet->getCell('G2')->getCalculatedValue();
$expectedResult = '1.0E+' . (PHP_FLOAT_DIG - 1);
self::assertSame($expectedResult, (string) $result);

$sheet->getCell('H1')->setValue(10.0 ** PHP_FLOAT_DIG + 1.2);
$sheet->getCell('H2')->setValue('=TRUNC(H1,1)');
$result = $sheet->getCell('H2')->getCalculatedValue();
$expectedResult = '1.0E+' . PHP_FLOAT_DIG;
self::assertSame($expectedResult, (string) $result);
}
}

0 comments on commit 7b478ad

Please sign in to comment.