/** * @param DecimalValue $margin * @param int $roundingExponent * * @return string|null Text */ private function formatMargin(DecimalValue $margin, $roundingExponent) { if ($this->options->getOption(self::OPT_SHOW_UNCERTAINTY_MARGIN)) { // TODO: never round to 0! See bug #56892 $roundedMargin = $this->decimalMath->roundToExponent($margin, $roundingExponent); if (!$roundedMargin->isZero()) { return $this->decimalFormatter->format($roundedMargin); } } return null; }
/** * @dataProvider roundToExponentProvider */ public function testRoundToExponent(DecimalValue $value, $digits, $expected) { $math = new DecimalMath(); $actual = $math->roundToExponent($value, $digits); $this->assertSame($expected, $actual->getValue()); }
/** * Returns a transformed value derived from this QuantityValue by applying * the given transformation to the amount and the upper and lower bounds. * The resulting amount and bounds are rounded to the significant number of * digits. Note that for exact quantities (with at least one bound equal to * the amount), no rounding is applied (since they are considered to have * infinite precision). * * The transformation is provided as a callback, which must implement a * monotonously increasing, fully differentiable function mapping a DecimalValue * to a DecimalValue. Typically, it will be a linear transformation applying a * factor and an offset. * * @param string $newUnit The unit of the transformed quantity. * * @param callable $transformation A callback that implements the desired transformation. * The transformation will be called three times, once for the amount, once * for the lower bound, and once for the upper bound. It must return a DecimalValue. * The first parameter passed to $transformation is the DecimalValue to transform * In addition, any extra parameters passed to transform() will be passed through * to the transformation callback. * * @param mixed ... Any extra parameters will be passed to the $transformation function. * * @throws InvalidArgumentException * @return QuantityValue */ public function transform($newUnit, $transformation) { if (!is_callable($transformation)) { throw new InvalidArgumentException('$transformation must be callable.'); } if (!is_string($newUnit)) { throw new InvalidArgumentException('$newUnit must be a string. Use "1" as the unit for unit-less quantities.'); } if ($newUnit === '') { throw new InvalidArgumentException('$newUnit must not be empty. Use "1" as the unit for unit-less quantities.'); } $oldUnit = $this->getUnit(); if ($newUnit === null) { $newUnit = $oldUnit; } // Apply transformation by calling the $transform callback. // The first argument for the callback is the DataValue to transform. In addition, // any extra arguments given for transform() are passed through. $args = func_get_args(); array_shift($args); $args[0] = $this->getAmount(); $amount = call_user_func_array($transformation, $args); $args[0] = $this->getUpperBound(); $upperBound = call_user_func_array($transformation, $args); $args[0] = $this->getLowerBound(); $lowerBound = call_user_func_array($transformation, $args); // use a preliminary QuantityValue to determine the significant number of digits $transformed = new self($amount, $newUnit, $upperBound, $lowerBound); $roundingExponent = $transformed->getOrderOfUncertainty(); // apply rounding to the significant digits $math = new DecimalMath(); $amount = $math->roundToExponent($amount, $roundingExponent); $upperBound = $math->roundToExponent($upperBound, $roundingExponent); $lowerBound = $math->roundToExponent($lowerBound, $roundingExponent); return new self($amount, $newUnit, $upperBound, $lowerBound); }