Skip to content

Commit

Permalink
Added support for the FLOOR.MATH and FLOOR.PRECISE functions
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul Kievits authored and PowerKiKi committed Apr 26, 2020
1 parent c4895b9 commit a6c56d0
Show file tree
Hide file tree
Showing 8 changed files with 295 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
### Added

- 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

Expand Down
10 changes: 10 additions & 0 deletions src/PhpSpreadsheet/Calculation/Calculation.php
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,16 @@ class Calculation
'functionCall' => [MathTrig::class, 'FLOOR'],
'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' => [
'category' => Category::CATEGORY_STATISTICAL,
'functionCall' => [Statistical::class, 'FORECAST'],
Expand Down
74 changes: 74 additions & 0 deletions src/PhpSpreadsheet/Calculation/MathTrig.php
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,80 @@ public static function FLOOR($number, $significance = null)
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)
{
return $b ? self::evaluateGCD($b, $a % $b) : $a;
Expand Down
2 changes: 2 additions & 0 deletions src/PhpSpreadsheet/Calculation/functionlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ FISHER
FISHERINV
FIXED
FLOOR
FLOOR.MATH
FLOOR.PRECISE
FORECAST
FREQUENCY
FTEST
Expand Down
Original file line number Diff line number Diff line change
@@ -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';
}
}
Original file line number Diff line number Diff line change
@@ -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';
}
}
89 changes: 89 additions & 0 deletions tests/data/Calculation/MathTrig/FLOORMATH.php
Original file line number Diff line number Diff line change
@@ -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
],
];
57 changes: 57 additions & 0 deletions tests/data/Calculation/MathTrig/FLOORPRECISE.php
Original file line number Diff line number Diff line change
@@ -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,
],
];

0 comments on commit a6c56d0

Please sign in to comment.