任何人都可以帮助 Dart 中银行家的舍入实现吗
所以我轮到 3 d.p.到最近的 2 d.p.数字 EXCEPT 当数字在中间时它会转到 最接近的偶数
例如
print(1.011.toStringAsFixed(2)); // rounds down to 1.01
print(1.019.toStringAsFixed(2)); // rounds up to 1.02
print(1.015.toStringAsFixed(2)); // rounds down to 1.01 but i want up to 1.02
print(1.025.toStringAsFixed(2)); // rounds down to 1.02
我有同样的要求,所以我建了一个。
banker_rounding.dart
import 'dart:math';
import 'package:decimal/decimal.dart';
Decimal _getDecimalOfNumber(Decimal number, int fractionDigits) => number - (number.floor());
Decimal _pow10(int powNum) => Decimal.parse(pow(10, powNum).toString());
Decimal _carryLatest(Decimal number) {
int decimalLength = number.toString().length - 2;
Decimal offset = _pow10(-decimalLength);
return number + offset;
}
Decimal bankerRound(Decimal value, int fractionDigits) {
// integer of number
Decimal integerOfNumber = value.floor();
// decimal of number
Decimal decimalOfNumber = _getDecimalOfNumber(value, fractionDigits);
// remain flag
int remainFlag = (decimalOfNumber * _pow10(fractionDigits + 1) % Decimal.fromInt(10)).toInt();
Decimal finalMultiple = _pow10(fractionDigits);
Decimal finalDecimalOfNumber = ((decimalOfNumber * finalMultiple).floor() / finalMultiple);
if (remainFlag <= 4) {
// do nothing
} else if (remainFlag >= 6) {
// carry
finalDecimalOfNumber = _carryLatest(finalDecimalOfNumber);
} else {
// check bottom has number
bool hasBottom = _getDecimalOfNumber(decimalOfNumber * _pow10(fractionDigits + 1), fractionDigits) != Decimal.zero;
if (hasBottom) {
// carry
finalDecimalOfNumber = _carryLatest(finalDecimalOfNumber);
} else {
// check pre remain flag
int preLastNumber = (decimalOfNumber * _pow10(fractionDigits) % Decimal.fromInt(10)).toInt();
if (preLastNumber.isOdd) {
// carry
finalDecimalOfNumber = _carryLatest(finalDecimalOfNumber);
} else {
// do nothing
}
}
}
return integerOfNumber + finalDecimalOfNumber;
}
这里是经过测试的庄家轮到整数的算法。 对于十进制(100% 准确):
import 'dart:math';
import 'package:decimal/decimal.dart';
var _halfDec = Decimal.parse('0.5');
Decimal bankerRoundDecimal(Decimal value) {
var rounded = value.round();
if(rounded - value == _halfDec)
if(value.ceil().toInt() % 2 != 0)
rounded = value.floor();
return rounded;
}
对于双人:
double bankerRound(double value) {
var rounded = value.roundToDouble();
if(((rounded - value) * 100).round() == 50)
if(value.ceil() % 2 != 0)
rounded = value.floorToDouble();
return rounded;
}
我按照这个 docuemnt 并为 Dart 写了另一个。
const double ROUNDING_EPSILON = 0.0000001;
double roundHalfEven(double value) {
if (value < 0.0) return -roundHalfEven(-value);
double epsilon = ROUNDING_EPSILON;
double ipart = value.toInt().toDouble();
// If 'value' is exctly halfway between two integers
if ((value - (ipart + 0.5)) < epsilon) {
// If 'ipart' is even then return 'ipart'
if (ipart % 2.0 < epsilon) {
return ipart;
}
// Else return the nearest even integer
return (ipart + 0.5).ceilToDouble();
}
// Otherwise use the usual round to closest
// (Either symmetric half-up or half-down will do0
return value.roundToDouble();
}
测试
import java.math.*
fun main() {
println(BigDecimal(4.5).setScale(0, RoundingMode.HALF_EVEN)) // 4
println(BigDecimal(3.5).setScale(0, RoundingMode.HALF_EVEN)) // 4
println(BigDecimal(4.500001).setScale(0, RoundingMode.HALF_EVEN)) // 5
println(BigDecimal(3.500001).setScale(0, RoundingMode.HALF_EVEN)) // 4
println("--------")
println(BigDecimal(-4.5).setScale(0, RoundingMode.HALF_EVEN)) // -4
println(BigDecimal(-3.5).setScale(0, RoundingMode.HALF_EVEN)) // -4
println(BigDecimal(-4.500001).setScale(0, RoundingMode.HALF_EVEN)) // -5
println(BigDecimal(-3.500001).setScale(0, RoundingMode.HALF_EVEN)) // -4
}
void main() {
print(roundHalfEven(4.5)); // 4
print(roundHalfEven(3.5)); // 4
print(roundHalfEven(4.500001)); // 5
print(roundHalfEven(3.500001)); // 4
print('-------');
print(roundHalfEven(-4.5)); // -4
print(roundHalfEven(-3.5)); // -4
print(roundHalfEven(-4.500001)); // -5
print(roundHalfEven(-3.500001)); // -4
}