withScale method
Convert to Decimal with specified scale and rounding mode
Implementation
Decimal withScale(int scale, RoundingMode mode) {
if (_scale == scale) {
return this;
}
if (_scale < scale) {
final factor = pow10(scale - _scale);
return Decimal(_value * factor, scale);
}
final factor = pow10(_scale - scale);
var rounded = _value ~/ factor;
final remainder = _value.remainder(factor);
final half = factor ~/ BigInt.two;
final isNegative = _value < BigInt.zero;
final absRemainder = remainder.abs();
switch (mode) {
case RoundingMode.up:
if (remainder != BigInt.zero) {
rounded = isNegative ? rounded - BigInt.one : rounded + BigInt.one;
}
break;
case RoundingMode.down:
break;
case RoundingMode.ceiling:
if (remainder != BigInt.zero && !isNegative) {
rounded = rounded + BigInt.one;
}
break;
case RoundingMode.floor:
if (remainder != BigInt.zero && isNegative) {
rounded = rounded - BigInt.one;
}
break;
case RoundingMode.halfUp:
if (absRemainder >= half) {
rounded = isNegative ? rounded - BigInt.one : rounded + BigInt.one;
}
break;
case RoundingMode.halfDown:
if (absRemainder > half) {
rounded = isNegative ? rounded - BigInt.one : rounded + BigInt.one;
}
break;
case RoundingMode.halfEven:
if (absRemainder > half) {
rounded = isNegative ? rounded - BigInt.one : rounded + BigInt.one;
} else if (absRemainder == half) {
if (rounded.isOdd) {
rounded = isNegative ? rounded - BigInt.one : rounded + BigInt.one;
}
}
break;
case RoundingMode.unnecessary:
if (remainder != BigInt.zero) {
throw ArgumentError(
'Rounding necessary: value cannot be represented exactly with scale $scale',
);
}
break;
}
return Decimal(rounded, scale);
}