给定一个double,我希望将它四舍五入到小数点后的给定精度点数,类似于PHP的round()函数。

我能在Dart文档中找到的最接近的东西是double.toStringAsPrecision(),但这不是我所需要的,因为它包括了精度总分中小数点前的数字。

例如,使用toStringAsPrecision(3):

0.123456789 rounds to 0.123  
9.123456789 rounds to 9.12  
98.123456789 rounds to 98.1  
987.123456789 rounds to 987  
9876.123456789 rounds to 9.88e+3

随着数字大小的增加,小数点后的精度也相应降低。


当前回答

num.toStringAsFixed()轮。它将你的num (n)转换成一个带有你想要的小数点数的字符串(2),然后在一行漂亮的代码中将它解析回你的num:

n = num.parse(n.toStringAsFixed(2));

其他回答

如果你想在文本中舍入double值。

文本(“$ {carpetprice.toStringAsFixed(3)}”,),

效果很好

var price=99.012334554
price = price.roundTodouble();
print(price); // 99.01

如果你想要使用特殊的舍入。您可以尝试这个函数(舍入)。

void main(List<String> arguments) {
list.map((e) {
 log('list1');
 rounding(e, 0.05);
 rounding(e, 0.1);
 rounding(e, 0.2);
 rounding(e, 0.25);
 rounding(e, 0.5);
 rounding(e, 1);
 rounding(e, 10);
}).toList();
list2.map((e) {
 log('list2');
 rounding(e, 0.05);
 rounding(e, 0.1);
 rounding(e, 0.2);
 rounding(e, 0.25);
 rounding(e, 0.5);
 rounding(e, 1);
 rounding(e, 10);
}).toList();
}

const list = [1.11, 1.22, 1.33, 1.44, 1.55, 1.66, 1.77, 1.88, 1.99];

const list2 = [2.19, 3.28, 4.37, 5.46, 6.55, 7.64, 8.73, 9.82, 10.91];

void rounding(double price, double count) {
log('-----------------------');
log('price: $price, count: $count');
double _priceRemainder = price % count;
double _someDiff = count / _priceRemainder;
log('_price: ${_priceRemainder.toStringAsFixed(2)}');
log('_pricePlus: ${_someDiff.toStringAsFixed(2)}');
if (_someDiff.toStringAsFixed(2) == '1.00') {
 log('_someDiff = 1');
} else if (_someDiff > 1 && _someDiff <= 2 ||
   _someDiff.toStringAsFixed(2) == '2.00') {
 log('_someDiff > 1 && _someDiff <= 2 || _someDiff.toStringAsFixed(2) == 2.00');
 log('ceilToDouble: $price: ${(price + (count - _priceRemainder)).toStringAsFixed(2)}');
 log('floorToDouble: $price: ${(price - _priceRemainder).toStringAsFixed(2)}');
 log('roundToDouble: $price: ${(price + (count - _priceRemainder)).toStringAsFixed(2)}');
} else if (_someDiff > 2) {
 log('_someDiff > 2');
 log('ceilToDouble: $price: ${(price + (count - _priceRemainder)).toStringAsFixed(2)}');
 log('floorToDouble: $price: ${(price - _priceRemainder).toStringAsFixed(2)}');
 log('roundToDouble: $price: ${(price - _priceRemainder).toStringAsFixed(2)}');
}
log('-----------------------');
}

调试控制台:


[log] price: 10.91, count: 0.05
[log] _price: 0.01
[log] _pricePlus: 5.00
[log] _someDiff > 2
[log] ceilToDouble: 10.91: 10.95
[log] floorToDouble: 10.91: 10.90
[log] roundToDouble: 10.91: 10.90
2
[log] -----------------------
[log] price: 10.91, count: 0.1
[log] _price: 0.01
[log] _pricePlus: 10.00
[log] _someDiff > 2
[log] ceilToDouble: 10.91: 11.00
[log] floorToDouble: 10.91: 10.90
[log] roundToDouble: 10.91: 10.90
2
[log] -----------------------
[log] price: 10.91, count: 0.2
[log] _price: 0.11
[log] _pricePlus: 1.82
[log] _someDiff > 1 && _someDiff <= 2 || _someDiff.toStringAsFixed(2) == 2.00
[log] ceilToDouble: 10.91: 11.00
[log] floorToDouble: 10.91: 10.80
[log] roundToDouble: 10.91: 11.00
2
[log] -----------------------
[log] price: 10.91, count: 0.25
[log] _price: 0.16
[log] _pricePlus: 1.56
[log] _someDiff > 1 && _someDiff <= 2 || _someDiff.toStringAsFixed(2) == 2.00
[log] ceilToDouble: 10.91: 11.00
[log] floorToDouble: 10.91: 10.75
[log] roundToDouble: 10.91: 11.00
2
[log] -----------------------
[log] price: 10.91, count: 0.5
[log] _price: 0.41
[log] _pricePlus: 1.22
[log] _someDiff > 1 && _someDiff <= 2 || _someDiff.toStringAsFixed(2) == 2.00
[log] ceilToDouble: 10.91: 11.00
[log] floorToDouble: 10.91: 10.50
[log] roundToDouble: 10.91: 11.00
2
[log] -----------------------
[log] price: 10.91, count: 1.0
[log] _price: 0.91
[log] _pricePlus: 1.10
[log] _someDiff > 1 && _someDiff <= 2 || _someDiff.toStringAsFixed(2) == 2.00
[log] ceilToDouble: 10.91: 11.00
[log] floorToDouble: 10.91: 10.00
[log] roundToDouble: 10.91: 11.00
2
[log] -----------------------
[log] price: 10.91, count: 10.0
[log] _price: 0.91
[log] _pricePlus: 10.99
[log] _someDiff > 2
[log] ceilToDouble: 10.91: 20.00
[log] floorToDouble: 10.91: 10.00
[log] roundToDouble: 10.91: 10.00

我认为公认的答案不是完美的解决方案,因为它转换为字符串。

如果你不想转换为字符串并返回双重使用 GetX包中的double.toPrecision(decimalNumber)。

如果你不想为此使用GetX(我强烈推荐GetX,它会改变你的生活),你可以复制和粘贴这个。

当你想使用扩展名时,请记住导入文件。

import 'dart:math';

extension Precision on double {
  double toPrecision(int fractionDigits) {
    var mod = pow(10, fractionDigits.toDouble()).toDouble();
    return ((this * mod).round().toDouble() / mod);
  }
}

这个DART四舍五入的问题已经出现了很长一段时间(@LucasMeadows),因为很明显直到现在这个问题还没有得到充分的解决(正如@DeepShah的观察所表明的那样)。

著名的舍入规则(未解决的问题):

“以数字5结尾的数字四舍五入:如果结果是偶数,则四舍五入;如果结果是奇数,则向下舍入。”

这是DART代码的解决方案:

double roundAccurately(double numToRound, int decimals) {

  // Step 1 - Prime IMPORTANT Function Parameters ...
  int iCutIndex = 0;
  String sDeciClipdNTR = "";
  num nMod = pow(10.0, decimals);
  String sNTR = numToRound.toString();
  int iLastDigitNTR = 0, i2ndLastDigitNTR = 0;
  debugPrint("Round => $numToRound to $decimals Decimal ${(decimals == 1) ? "Place" : "Places"} !!");   // Deactivate this 'print()' line in production code !!

  // Step 2 - Calculate Decimal Cut Index (i.e. string cut length) ...
  int iDeciPlaces = (decimals + 2);
  if (sNTR.contains('.')) {
    iCutIndex = sNTR.indexOf('.') + iDeciPlaces;
  } else {
    sNTR = sNTR + '.';
    iCutIndex = sNTR.indexOf('.') + iDeciPlaces;
  }

  // Step 3 - Cut input double to length of requested Decimal Places ...
  if (iCutIndex > sNTR.length) {                    // Check that decimal cutting is possible ...
    sNTR = sNTR + ("0" * iDeciPlaces);              // ... and fix (lengthen) the input double if it is too short.
    sDeciClipdNTR = sNTR.substring(0, iCutIndex);   // ... then cut string at indicated 'iCutIndex' !!
  } else {
    sDeciClipdNTR = sNTR.substring(0, iCutIndex);   // Cut string at indicated 'iCutIndex' !!
  }

  // Step 4 - Extract the Last and 2nd Last digits of the cut input double.
  int iLenSDCNTR = sDeciClipdNTR.length;
  iLastDigitNTR = int.parse(sDeciClipdNTR.substring(iLenSDCNTR - 1));   // Extract the last digit !!
  (decimals == 0)
    ? i2ndLastDigitNTR = int.parse(sDeciClipdNTR.substring(iLenSDCNTR - 3, iLenSDCNTR - 2))
    : i2ndLastDigitNTR = int.parse(sDeciClipdNTR.substring(iLenSDCNTR - 2, iLenSDCNTR - 1));

  // Step 5 - Execute the FINAL (Accurate) Rounding Process on the cut input double.
  double dAccuRound = 0;
  if (iLastDigitNTR == 5 && ((i2ndLastDigitNTR + 1) % 2 != 0)) {
    dAccuRound = double.parse(sDeciClipdNTR.substring(0, iLenSDCNTR - 1));
  } else {
    if (iLastDigitNTR < 5) {
      dAccuRound = double.parse(sDeciClipdNTR.substring(0, iLenSDCNTR - 1));
    } else {
      if (decimals == 0) {
        sDeciClipdNTR = sNTR.substring(0, iCutIndex - 2);
        dAccuRound = double.parse(sDeciClipdNTR) + 1;   // Finally - Round UP !!
      } else {
        double dModUnit = 1 / nMod;
        sDeciClipdNTR = sNTR.substring(0, iCutIndex - 1);
        dAccuRound = double.parse(sDeciClipdNTR) + dModUnit;   // Finally - Round UP !!
      }
    }
  }

  // Step 6 - Run final QUALITY CHECK !!
  double dResFin = double.parse(dAccuRound.toStringAsFixed(decimals));

  // Step 7 - Return result to function call ...
  debugPrint("Result (AccuRound) => $dResFin !!");   // Deactivate this 'print()' line in production code !!
  return dResFin;
}

这是一个完全手动的方法(可能有点过度),但它是有效的。请测试一下(直到耗尽),如果我没有做到,请告诉我。