Added support for the FLOOR.MATH and FLOOR.PRECISE functions

This commit is contained in:
Paul Kievits 2020-02-06 08:53:25 +01:00 committed by Adrien Crivelli
parent c4895b9468
commit a6c56d0f81
No known key found for this signature in database
GPG Key ID: B182FD79DC6DE92E
8 changed files with 295 additions and 0 deletions

View File

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
### Added ### Added
- Improved the ARABIC function to also hande short-hand roman numerals - Improved the ARABIC function to also hande short-hand roman numerals
- Added support for the FLOOR.MATH and FLOOR.PRECISE functions [#1351](https://github.com/PHPOffice/PhpSpreadsheet/pull/1351)
### Fixed ### Fixed

View File

@ -914,6 +914,16 @@ class Calculation
'functionCall' => [MathTrig::class, 'FLOOR'], 'functionCall' => [MathTrig::class, 'FLOOR'],
'argumentCount' => '2', 'argumentCount' => '2',
], ],
'FLOOR.MATH' => [
'category' => Category::CATEGORY_MATH_AND_TRIG,
'functionCall' => [MathTrig::class, 'FLOORMATH'],
'argumentCount' => '3',
],
'FLOOR.PRECISE' => [
'category' => Category::CATEGORY_MATH_AND_TRIG,
'functionCall' => [MathTrig::class, 'FLOORPRECISE'],
'argumentCount' => '2',
],
'FORECAST' => [ 'FORECAST' => [
'category' => Category::CATEGORY_STATISTICAL, 'category' => Category::CATEGORY_STATISTICAL,
'functionCall' => [Statistical::class, 'FORECAST'], 'functionCall' => [Statistical::class, 'FORECAST'],

View File

@ -438,6 +438,80 @@ class MathTrig
return Functions::VALUE(); return Functions::VALUE();
} }
/**
* FLOOR.MATH.
*
* Round a number down to the nearest integer or to the nearest multiple of significance.
*
* Excel Function:
* FLOOR.MATH(number[,significance[,mode]])
*
* @category Mathematical and Trigonometric Functions
*
* @param float $number Number to round
* @param float $significance Significance
* @param int $mode direction to round negative numbers
*
* @return float|string Rounded Number, or a string containing an error
*/
public static function FLOORMATH($number, $significance = null, $mode = 0)
{
$number = Functions::flattenSingleValue($number);
$significance = Functions::flattenSingleValue($significance);
$mode = Functions::flattenSingleValue($mode);
if (is_numeric($number) && $significance === null) {
$significance = $number / abs($number);
}
if (is_numeric($number) && is_numeric($significance) && is_numeric($mode)) {
if ($significance == 0.0) {
return Functions::DIV0();
} elseif ($number == 0.0) {
return 0.0;
} elseif (self::SIGN($significance) == -1 || (self::SIGN($number) == -1 && !empty($mode))) {
return ceil($number / $significance) * $significance;
}
return floor($number / $significance) * $significance;
}
return Functions::VALUE();
}
/**
* FLOOR.PRECISE.
*
* Rounds number down, toward zero, to the nearest multiple of significance.
*
* Excel Function:
* FLOOR.PRECISE(number[,significance])
*
* @category Mathematical and Trigonometric Functions
*
* @param float $number Number to round
* @param float $significance Significance
*
* @return float|string Rounded Number, or a string containing an error
*/
public static function FLOORPRECISE($number, $significance = 1)
{
$number = Functions::flattenSingleValue($number);
$significance = Functions::flattenSingleValue($significance);
if ((is_numeric($number)) && (is_numeric($significance))) {
if ($significance == 0.0) {
return Functions::DIV0();
} elseif ($number == 0.0) {
return 0.0;
}
return floor($number / abs($significance)) * abs($significance);
}
return Functions::VALUE();
}
private static function evaluateGCD($a, $b) private static function evaluateGCD($a, $b)
{ {
return $b ? self::evaluateGCD($b, $a % $b) : $a; return $b ? self::evaluateGCD($b, $a % $b) : $a;

View File

@ -139,6 +139,8 @@ FISHER
FISHERINV FISHERINV
FIXED FIXED
FLOOR FLOOR
FLOOR.MATH
FLOOR.PRECISE
FORECAST FORECAST
FREQUENCY FREQUENCY
FTEST FTEST

View File

@ -0,0 +1,31 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
use PHPUnit\Framework\TestCase;
class FloorMathTest extends TestCase
{
public function setUp()
{
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
}
/**
* @dataProvider providerFLOORMATH
*
* @param mixed $expectedResult
*/
public function testFLOORMATH($expectedResult, ...$args)
{
$result = MathTrig::FLOORMATH(...$args);
$this->assertEquals($expectedResult, $result, '', 1E-12);
}
public function providerFLOORMATH()
{
return require 'data/Calculation/MathTrig/FLOORMATH.php';
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\MathTrig;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
use PHPUnit\Framework\TestCase;
class FloorPreciseTest extends TestCase
{
public function setUp()
{
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
}
/**
* @dataProvider providerFLOORPRECISE
*
* @param mixed $expectedResult
*/
public function testFLOOR($expectedResult, ...$args)
{
$result = MathTrig::FLOORPRECISE(...$args);
$this->assertEquals($expectedResult, $result, '', 1E-12);
}
public function providerFLOORPRECISE()
{
return require 'data/Calculation/MathTrig/FLOORPRECISE.php';
}
}

View File

@ -0,0 +1,89 @@
<?php
return [
[
2,
2.5,
1,
],
[
-4,
-2.5,
-2,
],
[
-4,
-2.5,
2,
],
[
2,
2.5,
-2,
],
[
'#DIV/0!',
123.456,
0,
],
[
1.5,
1.5,
0.10000000000000001,
],
[
0.23000000000000001,
0.23400000000000001,
0.01,
],
[
123,
123.456,
],
[
'#VALUE!',
'ABC',
],
[
15,
17,
3,
],
[
16,
19,
4,
],
[
20,
24.3,
5
],
[
6,
6.7
],
[
-10,
-8.1,
2
],
[
-4,
-5.5,
2,
-1
],
[
-4,
-5.5,
2,
1
],
[
-6,
-5.5,
2,
0
],
];

View File

@ -0,0 +1,57 @@
<?php
return [
[
2,
2.5,
1,
],
[
-4,
-2.5,
-2,
],
[
-4,
-2.5,
2,
],
[
2,
2.5,
-2,
],
[
'#DIV/0!',
123.456,
0,
],
[
1.5,
1.5,
0.10000000000000001,
],
[
0.23000000000000001,
0.23400000000000001,
0.01,
],
[
123,
123.456,
],
[
'#VALUE!',
'ABC',
],
[
15,
17,
3,
],
[
16,
19,
4,
],
];