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

View File

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

View File

@ -354,6 +354,16 @@ abstract class BigNumber
*/ */
abstract public function toBigRational(); 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. * 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; return $this;
} }
/**
* {@inheritdoc}
*/
public function toScale($scale, $roundingMode = RoundingMode::UNNECESSARY)
{
return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode);
}
/** /**
* {@inheritdoc} * {@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 * @dataProvider providerToInteger
* *

View File

@ -4,6 +4,7 @@ namespace Brick\Math\Tests;
use Brick\Math\BigInteger; use Brick\Math\BigInteger;
use Brick\Math\BigRational; use Brick\Math\BigRational;
use Brick\Math\RoundingMode;
use Brick\Math\Exception\RoundingNecessaryException; 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 * @dataProvider providerToInteger
* *