给定一个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

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


当前回答

这个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;
}

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

其他回答

您可以调用此函数来获得黑暗(颤振)的精确程度。 Double eval -> Double想要转换的 Int I ->返回的小数点。

double doubleToPrecision(double eval, int i) {
double step1 = eval;//1/3
print(step1); // 0.3333333333333333

String step2 = step1.toStringAsFixed(2);
print(step2); // 0.33

double step3 = double.parse(step2);
print(step3); // 0.33
eval = step3;
return eval; }

如果使用动态类型的数据。你可以使用它。

 typeDecimal(data) => num.parse(data.toString()).toStringAsFixed(2);
var price = 99.012334554;
price = price.toStringAsFixed(2);
print(price); // 99.01

这是dart的ref。 裁判:https://api.dartlang.org/stable/2.3.0/dart-core/num/toStringAsFixed.html

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

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

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

如果你不想转换为字符串并返回双重使用 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);
  }
}