1
0
mirror of https://github.com/danog/math.git synced 2024-11-26 20:04:46 +01:00

Add BigNumber::toScale()

This allows to convert any BigNumber to a BigDecimal of the given scale.
This commit is contained in:
Benjamin Morel 2015-07-05 13:07:10 +02:00
parent 0fa9a802c6
commit c1bdb3b9b5
6 changed files with 107 additions and 5 deletions

View File

@ -418,6 +418,8 @@ final class BigDecimal extends BigNumber implements \Serializable
/**
* Returns a BigDecimal with the current value and the specified scale.
*
* @deprecated Use `toScale()`.
*
* @param int $scale
* @param int $roundingMode
*
@ -425,11 +427,7 @@ final class BigDecimal extends BigNumber implements \Serializable
*/
public function withScale($scale, $roundingMode = RoundingMode::UNNECESSARY)
{
if ($scale == $this->scale) {
return $this;
}
return $this->dividedBy(1, $scale, $roundingMode);
return $this->toScale($scale, $roundingMode);
}
/**
@ -654,6 +652,20 @@ final class BigDecimal extends BigNumber implements \Serializable
return BigRational::create($numerator, $denominator, false);
}
/**
* {@inheritdoc}
*/
public function toScale($scale, $roundingMode = RoundingMode::UNNECESSARY)
{
$scale = (int) $scale;
if ($scale === $this->scale) {
return $this;
}
return $this->dividedBy(BigDecimal::one(), $scale, $roundingMode);
}
/**
* {@inheritdoc}
*/

View File

@ -471,6 +471,14 @@ final class BigInteger extends BigNumber implements \Serializable
return BigRational::create($this, BigInteger::one(), false);
}
/**
* {@inheritdoc}
*/
public function toScale($scale, $roundingMode = RoundingMode::UNNECESSARY)
{
return $this->toBigDecimal()->toScale($scale, $roundingMode);
}
/**
* {@inheritdoc}
*/

View File

@ -354,6 +354,16 @@ abstract class BigNumber
*/
abstract public function toBigRational();
/**
* Converts this number to a BigDecimal with the given scale, using rounding if necessary.
*
* @param int $scale The scale of the resulting `BigDecimal`.
* @param int $roundingMode A `RoundingMode` constant.
*
* @return BigDecimal
*/
abstract public function toScale($scale, $roundingMode = RoundingMode::UNNECESSARY);
/**
* Returns the exact value of this number as a native integer.
*

View File

@ -388,6 +388,14 @@ final class BigRational extends BigNumber implements \Serializable
return $this;
}
/**
* {@inheritdoc}
*/
public function toScale($scale, $roundingMode = RoundingMode::UNNECESSARY)
{
return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode);
}
/**
* {@inheritdoc}
*/

View File

@ -1678,6 +1678,30 @@ class BigIntegerTest extends AbstractTestCase
];
}
/**
* @dataProvider providerToScale
*
* @param string $number
* @param int $scale
* @param string $expected
*/
public function testToScale($number, $scale, $expected)
{
$this->assertBigDecimalEquals($expected, BigInteger::of($number)->toScale($scale));
}
/**
* @return array
*/
public function providerToScale()
{
return [
['12345678901234567890123456789', 0, '12345678901234567890123456789'],
['12345678901234567890123456789', 1, '12345678901234567890123456789.0'],
['12345678901234567890123456789', 2, '12345678901234567890123456789.00'],
];
}
/**
* @dataProvider providerToInteger
*

View File

@ -4,6 +4,7 @@ namespace Brick\Math\Tests;
use Brick\Math\BigInteger;
use Brick\Math\BigRational;
use Brick\Math\RoundingMode;
use Brick\Math\Exception\RoundingNecessaryException;
/**
@ -833,6 +834,45 @@ class BigRationalTest extends AbstractTestCase
}
}
/**
* @dataProvider providerToScale
*
* @param string $number
* @param int $scale
* @param int $roundingMode
* @param string $expected
*/
public function testToScale($number, $scale, $roundingMode, $expected)
{
$number = BigRational::of($number);
if ($this->isException($expected)) {
$this->setExpectedException($expected);
}
$actual = $number->toScale($scale, $roundingMode);
if (! $this->isException($expected)) {
$this->assertBigDecimalEquals($expected, $actual);
}
}
/**
* @return array
*/
public function providerToScale()
{
return [
['1/8', 3, RoundingMode::UNNECESSARY, '0.125'],
['1/16', 3, RoundingMode::UNNECESSARY, RoundingNecessaryException::class],
['1/16', 3, RoundingMode::HALF_DOWN, '0.062'],
['1/16', 3, RoundingMode::HALF_UP, '0.063'],
['1/9', 30, RoundingMode::DOWN, '0.111111111111111111111111111111'],
['1/9', 30, RoundingMode::UP, '0.111111111111111111111111111112'],
['1/9', 100, RoundingMode::UNNECESSARY, RoundingNecessaryException::class],
];
}
/**
* @dataProvider providerToInteger
*