toStringAsFixed() 返回 Dart 中给定数字的向上取整值

问题描述 投票:0回答:2

我想得到

double
Dart
的小数点后一位。我使用
toStringAsFixed()
方法获取它,但它返回一个向上取整的值。

double d1 = 1.151;
double d2 = 1.150;

print('$d1 is ${d1.toStringAsFixed(1)}');
print('$d2 is ${d2.toStringAsFixed(1)}');

Console output:
1.151 is 1.2
1.15 is 1.1

如何在没有四舍五入的情况下获得它?也喜欢

1.1
代表
1.151
。预先感谢。

dart double precision
2个回答
2
投票

Not四舍五入对我来说似乎非常有问题1,但如果您真的想要截断字符串表示而不进行四舍五入,那么我会采用字符串表示形式,找到小数点,并创建适当的子字符串。

有一些潜在的陷阱:

  • 该值可能太大,以至于其正常字符串表示形式为指数形式。请注意,对于如此大的数字,
    double.toStringAsFixed
    无论如何都只会返回指数形式,因此也许可以做同样的事情。
  • 该值可能非常小,以至于其正常字符串表示形式为指数形式。
    double.toStringAsFixed
    已经处理了这个问题,因此不要使用
    double.toString
    ,而是使用具有最大小数位数的
    double.toStringAsFixed
  • 该值可能根本没有小数点(例如 NaN、+无穷大、-无穷大)。只需按原样返回这些值即可。
extension on double {
  // Like [toStringAsFixed] but truncates (toward zero) to the specified
  // number of fractional digits instead of rounding.
  String toStringAsTruncated(int fractionDigits) {
    // Require same limits as [toStringAsFixed].
    assert(fractionDigits >= 0);
    assert(fractionDigits <= 20);
    
    if (fractionDigits == 0) {
      return truncateToDouble().toString();
    }

    // [toString] will represent very small numbers in exponential form.
    // Instead use [toStringAsFixed] with the maximum number of fractional
    // digits.
    var s = toStringAsFixed(20);

    // [toStringAsFixed] will still represent very large numbers in
    // exponential form.
    if (s.contains('e')) {
      // Ignore values in exponential form.
      return s;
    }

    // Ignore unrecognized values (e.g. NaN, +infinity, -infinity).
    var i = s.indexOf('.');
    if (i == -1) {
      return s;
    }

    return s.substring(0, i + fractionDigits + 1);
  }
}

void main() {
  var values = [
    1.151,
    1.15,
    1.1999,
    -1.1999,
    1.0,
    1e21,
    1e-20,
    double.nan,
    double.infinity,
    double.negativeInfinity,
  ];

  for (var v in values) {
    print(v.toStringAsTruncated(1));
  }
}

人们可能考虑的另一种方法是乘以

pow(10, fractionalDigits)
,使用
double.truncateToDouble
,除以之前使用的 10 次方,然后使用
.toStringAsFixed(fractionalDigits)
。这可能适用于人类缩放的值,但由于浮点运算的精度损失,它可能会为非常大的值生成意外的结果。 (不过,如果您使用
package:decimal
而不是
double
,这种方法就会起作用。)


1 不四舍五入似乎特别糟糕,因为使用

double
来表示以 10 为基数的小数本质上是不精确的。例如,由于最接近 0.7 的 IEEE-754 双精度浮点数是 0.6999999999999999555910790149937383830547332763671875,您是否真的希望
0.7.toStringAsTruncated(1)
返回
'0.6'
而不是
'0.7'


0
投票

最近我通过以下自定义方法解决了此类任务。

String coinFormatFixedNew(num? number, {int? fixed}) {
 number = number ?? 0;
 fixed = fixed ?? 4;
 String numberStr = number.toDouble().toString();
 final numList = numberStr.split(".").toList();

 if (fixed == 0) {
  return numList[0];
 } else {
  numberStr = numList[1];
  if (numberStr.length >= fixed) {
  numberStr = numberStr.substring(0, fixed);
  }
 return "${numList[0]}.$numberStr";
 }
}

它将针对您的值 1.1511.150 返回 1.1

© www.soinside.com 2019 - 2024. All rights reserved.