Too Many Digits

We can't handle more digits than Php allows. Neither can Excel. Just do our best without throwing an Error.
This commit is contained in:
oleibman
2024-07-30 21:17:50 -07:00
parent e39dfe341f
commit 7b478adaeb
2 changed files with 38 additions and 1 deletions
@@ -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
@@ -52,7 +57,7 @@ class Trunc
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);
@@ -47,4 +47,36 @@ class TruncTest extends AllSetupTeardown
'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);
}
}