예제 #1
0
 /**
  * @see ValueFormatter::format
  *
  * @since 0.1
  *
  * @param DecimalValue $dataValue
  *
  * @throws InvalidArgumentException
  * @return string Text
  */
 public function format($dataValue)
 {
     if (!$dataValue instanceof DecimalValue) {
         throw new InvalidArgumentException('Data value type mismatch. Expected a DecimalValue.');
     }
     // TODO: Implement optional rounding/padding
     $decimal = $dataValue->getValue();
     if (!$this->getOption(self::OPT_FORCE_SIGN)) {
         // strip leading +
         $decimal = ltrim($decimal, '+');
     }
     // apply number localization
     $decimal = $this->localizer->localizeNumber($decimal);
     return $decimal;
 }
예제 #2
0
 /**
  * Compares this DecimalValue to another DecimalValue.
  *
  * @since 0.1
  *
  * @param DecimalValue $that
  *
  * @throws LogicException
  * @return int +1 if $this > $that, 0 if $this == $that, -1 if $this < $that
  */
 public function compare(DecimalValue $that)
 {
     if ($this === $that) {
         return 0;
     }
     $a = $this->getValue();
     $b = $that->getValue();
     if ($a === $b) {
         return 0;
     }
     if ($a[0] === '+' && $b[0] === '-') {
         return 1;
     }
     if ($a[0] === '-' && $b[0] === '+') {
         return -1;
     }
     // compare the integer parts
     $aInt = ltrim($this->getIntegerPart(), '0');
     $bInt = ltrim($that->getIntegerPart(), '0');
     $sense = $a[0] === '+' ? 1 : -1;
     // per precondition, there are no leading zeros, so the longer nummber is greater
     if (strlen($aInt) > strlen($bInt)) {
         return $sense;
     }
     if (strlen($aInt) < strlen($bInt)) {
         return -$sense;
     }
     // if both have equal length, compare alphanumerically
     $cmp = strcmp($aInt, $bInt);
     if ($cmp > 0) {
         return $sense;
     }
     if ($cmp < 0) {
         return -$sense;
     }
     // compare fractional parts
     $aFract = rtrim($this->getFractionalPart(), '0');
     $bFract = rtrim($that->getFractionalPart(), '0');
     // the fractional part is left-aligned, so just check alphanumeric ordering
     $cmp = strcmp($aFract, $bFract);
     return $cmp > 0 ? $sense : ($cmp < 0 ? -$sense : 0);
 }
예제 #3
0
 /**
  * Shift the decimal point according to the given exponent.
  *
  * @param DecimalValue $decimal
  * @param int $exponent The exponent to apply (digits to shift by). A Positive exponent
  * shifts the decimal point to the right, a negative exponent shifts to the left.
  *
  * @throws InvalidArgumentException
  * @return DecimalValue
  */
 public function shift(DecimalValue $decimal, $exponent)
 {
     if (!is_int($exponent)) {
         throw new InvalidArgumentException('$exponent must be an integer');
     }
     if ($exponent == 0) {
         return $decimal;
     }
     $sign = $decimal->getSign();
     $intPart = $decimal->getIntegerPart();
     $fractPart = $decimal->getFractionalPart();
     if ($exponent < 0) {
         $intPart = $this->shiftLeft($intPart, $exponent);
     } else {
         $fractPart = $this->shiftRight($fractPart, $exponent);
     }
     $digits = $sign . $intPart . $fractPart;
     $digits = $this->stripLeadingZeros($digits);
     return new DecimalValue($digits);
 }
예제 #4
0
 /**
  * Returns a QuantityValue representing the given amount, automatically assuming
  * a level of uncertainty based on the digits given.
  *
  * The upper and lower bounds are determined automatically from the given
  * digits by increasing resp. decreasing the least significant digit.
  * E.g. "+0.01" would have upperBound "+0.02" and lowerBound "+0.01",
  * while "-100" would have upperBound "-99" and lowerBound "-101".
  *
  * @param DecimalValue $amount The quantity
  * @param string $unit The quantity's unit (use "1" for unit-less quantities)
  * @param int $exponent Decimal exponent to apply
  *
  * @return QuantityValue
  */
 private function newUncertainQuantityFromDigits(DecimalValue $amount, $unit = '1', $exponent = 0)
 {
     $math = new DecimalMath();
     if ($amount->getSign() === '+') {
         $upperBound = $math->bump($amount);
         $lowerBound = $math->slump($amount);
     } else {
         $upperBound = $math->slump($amount);
         $lowerBound = $math->bump($amount);
     }
     $amount = $this->decimalParser->applyDecimalExponent($amount, $exponent);
     $lowerBound = $this->decimalParser->applyDecimalExponent($lowerBound, $exponent);
     $upperBound = $this->decimalParser->applyDecimalExponent($upperBound, $exponent);
     return new QuantityValue($amount, $unit, $upperBound, $lowerBound);
 }
예제 #5
0
 /**
  * @dataProvider isZeroProvider
  */
 public function testIsZero(DecimalValue $value, $expected)
 {
     $actual = $value->isZero();
     $this->assertSame($expected, $actual);
 }
예제 #6
0
 /**
  * @dataProvider applyDecimalExponentProvider
  */
 public function testApplyDecimalExponent(DecimalValue $decimal, $exponent, DecimalValue $expectedDecimal)
 {
     $parser = new DecimalParser();
     $actualDecimal = $parser->applyDecimalExponent($decimal, $exponent);
     $this->assertSame($expectedDecimal->getValue(), $actualDecimal->getValue());
 }
예제 #7
0
 /**
  * Constructs a new instance of the DataValue from the provided data.
  * This can round-trip with @see getArrayValue
  *
  * @since 0.1
  *
  * @param mixed $data
  *
  * @return QuantityValue
  * @throws IllegalValueException
  */
 public static function newFromArray($data)
 {
     self::requireArrayFields($data, array('amount', 'unit', 'upperBound', 'lowerBound'));
     return new static(DecimalValue::newFromArray($data['amount']), $data['unit'], DecimalValue::newFromArray($data['upperBound']), DecimalValue::newFromArray($data['lowerBound']));
 }