Exemple #1
0
 public function matchBest($value, $pos = 7)
 {
     /*
      * Have to use this instead of scalar type hints. Because we are dealing with arbitrarily large numbers, we are
      * using the bc math extension. This means that all numbers are actually strings in order to retain precision.
      *
      * If we used the int or float type hints, PHP 7 would cast string values (which is good), but that would lose
      * precision in the cast (which is bad).
      *
      * is_numeric will achieve the desired effect without altering the $value
      */
     if (!is_numeric($value)) {
         throw new \Exception('Cannot pass a non-numeric value.');
     }
     // The number is more than three orders of magnitude from zero
     if ($value >= 1000 || $value <= -1000) {
         // Increase the exponent by three and try again
         return $this->matchBest(MathProvider::divide($value, 1000), $pos + 1);
     }
     // The number is a decimal less than one from zero
     if ($value < 1 && $value > -1 && $value != 0) {
         // Decrease the exponent by three and try again
         return $this->matchBest(MathProvider::multiply($value, 1000), $pos - 1);
     }
     // If no transformation is needed, we have a special case of the return
     if ($pos == 7) {
         return ['value' => $value, 'scale' => '1', 'prefix' => ''];
     }
     // Otherwise, we have our answer
     return ['value' => $value, 'scale' => $this->scale[$this->order[$pos]], 'prefix' => $this->order[$pos]];
 }
Exemple #2
0
 /**
  * @param Length                $distance
  * @param Acceleration          $acceleration
  * @param UnitComposition|null  $unitComposition
  *
  * @return Time
  */
 public static function timeFromConstantAccel(Length $distance, Acceleration $acceleration, UnitComposition $unitComposition = null)
 {
     if (is_null($unitComposition)) {
         $unitComposition = new UnitComposition();
     }
     $distance->toNative();
     $acceleration->toNative();
     return new Time(MathProvider::squareRoot(MathProvider::multipleMultiply(2, $distance->getValue(), $acceleration->getValue())), $unitComposition);
 }
Exemple #3
0
 public function subtract(Quantity $quantity)
 {
     if (get_class($this) != get_class($quantity)) {
         throw new \Exception('Cannot subtract units of two different types.');
     }
     $oldUnit = $quantity->getUnit();
     $this->value = MathProvider::subtract($this->value, $quantity->to($this->unit)->getValue());
     $quantity->to($oldUnit);
     return $this;
 }
Exemple #4
0
 /**
  * @param Quantity[] $mults
  * @param Quantity[] $divides
  * @param int        $precision
  */
 public function naiveMultiOpt(array $mults, array $divides, $precision = 2)
 {
     $newUnit = $this->getMultiUnits($mults, $divides);
     $newVal = 1;
     foreach ($mults as $quantity) {
         $newVal = MathProvider::multiply($newVal, $quantity->toNative()->getValue());
     }
     foreach ($divides as $quantity) {
         $newVal = MathProvider::divide($newVal, $quantity->toNative()->getValue(), $precision);
     }
     return $newUnit->preConvertedAdd($newVal);
 }