1<?php 2 3namespace PhpOffice\PhpSpreadsheet\Calculation\MathTrig; 4 5use PhpOffice\PhpSpreadsheet\Calculation\Exception; 6use PhpOffice\PhpSpreadsheet\Calculation\Functions; 7 8class Floor 9{ 10 private static function floorCheck1Arg(): void 11 { 12 $compatibility = Functions::getCompatibilityMode(); 13 if ($compatibility === Functions::COMPATIBILITY_EXCEL) { 14 throw new Exception('Excel requires 2 arguments for FLOOR'); 15 } 16 } 17 18 /** 19 * FLOOR. 20 * 21 * Rounds number down, toward zero, to the nearest multiple of significance. 22 * 23 * Excel Function: 24 * FLOOR(number[,significance]) 25 * 26 * @param mixed $number Expect float. Number to round 27 * @param mixed $significance Expect float. Significance 28 * 29 * @return float|string Rounded Number, or a string containing an error 30 */ 31 public static function floor($number, $significance = null) 32 { 33 if ($significance === null) { 34 self::floorCheck1Arg(); 35 } 36 37 try { 38 $number = Helpers::validateNumericNullBool($number); 39 $significance = Helpers::validateNumericNullSubstitution($significance, ($number < 0) ? -1 : 1); 40 } catch (Exception $e) { 41 return $e->getMessage(); 42 } 43 44 return self::argumentsOk((float) $number, (float) $significance); 45 } 46 47 /** 48 * FLOOR.MATH. 49 * 50 * Round a number down to the nearest integer or to the nearest multiple of significance. 51 * 52 * Excel Function: 53 * FLOOR.MATH(number[,significance[,mode]]) 54 * 55 * @param mixed $number Number to round 56 * @param mixed $significance Significance 57 * @param mixed $mode direction to round negative numbers 58 * 59 * @return float|string Rounded Number, or a string containing an error 60 */ 61 public static function math($number, $significance = null, $mode = 0) 62 { 63 try { 64 $number = Helpers::validateNumericNullBool($number); 65 $significance = Helpers::validateNumericNullSubstitution($significance, ($number < 0) ? -1 : 1); 66 $mode = Helpers::validateNumericNullSubstitution($mode, null); 67 } catch (Exception $e) { 68 return $e->getMessage(); 69 } 70 71 return self::argsOk((float) $number, (float) $significance, (int) $mode); 72 } 73 74 /** 75 * FLOOR.PRECISE. 76 * 77 * Rounds number down, toward zero, to the nearest multiple of significance. 78 * 79 * Excel Function: 80 * FLOOR.PRECISE(number[,significance]) 81 * 82 * @param float $number Number to round 83 * @param float $significance Significance 84 * 85 * @return float|string Rounded Number, or a string containing an error 86 */ 87 public static function precise($number, $significance = 1) 88 { 89 try { 90 $number = Helpers::validateNumericNullBool($number); 91 $significance = Helpers::validateNumericNullSubstitution($significance, null); 92 } catch (Exception $e) { 93 return $e->getMessage(); 94 } 95 96 return self::argumentsOkPrecise((float) $number, (float) $significance); 97 } 98 99 /** 100 * Avoid Scrutinizer problems concerning complexity. 101 * 102 * @return float|string 103 */ 104 private static function argumentsOkPrecise(float $number, float $significance) 105 { 106 if ($significance == 0.0) { 107 return Functions::DIV0(); 108 } 109 if ($number == 0.0) { 110 return 0.0; 111 } 112 113 return floor($number / abs($significance)) * abs($significance); 114 } 115 116 /** 117 * Avoid Scrutinizer complexity problems. 118 * 119 * @return float|string Rounded Number, or a string containing an error 120 */ 121 private static function argsOk(float $number, float $significance, int $mode) 122 { 123 if (!$significance) { 124 return Functions::DIV0(); 125 } 126 if (!$number) { 127 return 0.0; 128 } 129 if (self::floorMathTest($number, $significance, $mode)) { 130 return ceil($number / $significance) * $significance; 131 } 132 133 return floor($number / $significance) * $significance; 134 } 135 136 /** 137 * Let FLOORMATH complexity pass Scrutinizer. 138 */ 139 private static function floorMathTest(float $number, float $significance, int $mode): bool 140 { 141 return Helpers::returnSign($significance) == -1 || (Helpers::returnSign($number) == -1 && !empty($mode)); 142 } 143 144 /** 145 * Avoid Scrutinizer problems concerning complexity. 146 * 147 * @return float|string 148 */ 149 private static function argumentsOk(float $number, float $significance) 150 { 151 if ($significance == 0.0) { 152 return Functions::DIV0(); 153 } 154 if ($number == 0.0) { 155 return 0.0; 156 } 157 if (Helpers::returnSign($significance) == 1) { 158 return floor($number / $significance) * $significance; 159 } 160 if (Helpers::returnSign($number) == -1 && Helpers::returnSign($significance) == -1) { 161 return floor($number / $significance) * $significance; 162 } 163 164 return Functions::NAN(); 165 } 166} 167