43

I would like the optimal solution for removing trailing zeros using Dart. If I have a double that is 12.0 it should output 12. If I have a double that is 12.5 it should output 12.5

John
  • 2,551
  • 3
  • 17
  • 29

21 Answers21

60

I made regular expression pattern for that feature.

double num = 12.50; // 12.5
double num2 = 12.0; // 12
double num3 = 1000; // 1000

RegExp regex = RegExp(r'([.]*0)(?!.*\d)');

String s = num.toString().replaceAll(regex, '');
Tumist
  • 119
  • 3
  • 11
Yuna
  • 1,323
  • 10
  • 8
23

UPDATE
A better approach, just use this method:

String removeDecimalZeroFormat(double n) {
    return n.toStringAsFixed(n.truncateToDouble() == n ? 0 : 1);
}

OLD
This meets the requirements:

double x = 12.0;
double y = 12.5;

print(x.toString().replaceAll(RegExp(r'.0'), ''));
print(y.toString().replaceAll(RegExp(r'.0'), ''));

X Output: 12
Y Output: 12.5

John
  • 2,551
  • 3
  • 17
  • 29
19

Use NumberFormat:

String formatQuantity(double v) {
  if (v == null) return '';

  NumberFormat formatter = NumberFormat();
  formatter.minimumFractionDigits = 0;
  formatter.maximumFractionDigits = 2;
  return formatter.format(v);
}
greensuisse
  • 1,727
  • 16
  • 18
13

Lots of the answers don't work for numbers with many decimal points and are centered around monetary values.

To remove all trailing zeros regardless of length:

removeTrailingZeros(String n) {
  return n.replaceAll(RegExp(r"([.]*0+)(?!.*\d)"), "");
}

Input: 12.00100003000

Output: 12.00100003

If you only want to remove trailing 0's that come after a decimal point, use this instead:

removeTrailingZerosAndNumberfy(String n) {
    if(n.contains('.')){
      return double.parse(
        n.replaceAll(RegExp(r"([.]*0+)(?!.*\d)"), "") //remove all trailing 0's and extra decimals at end if any
      );
    }
    else{
      return double.parse(
        n
      );
    }
  }
August Kimo
  • 1,503
  • 8
  • 17
10

If what you want is to convert a double without decimals to an int but keep it as a double if it has decimals, I use this method:

num doubleWithoutDecimalToInt(double val) {
  return val % 1 == 0 ? val.toInt() : val;
}
SimonC
  • 365
  • 3
  • 11
6

I found another solution, to use num instead of double. In my case I'm parsing String to num:

void main() {
 print(num.parse('50.05').toString()); //prints 50.05
 print(num.parse('50.0').toString()); //prints 50
}
dudeck
  • 393
  • 5
  • 13
4

Here is what I've come up with:

extension DoubleExtensions on double {
  String toStringWithoutTrailingZeros() {
    if (this == null) return null;
    return truncateToDouble() == this ? toInt().toString() : toString();
  }
}


void main() {
  group('DoubleExtensions', () {
    test("toStringWithoutTrailingZeros's result matches the expected value for a given double",
        () async {
      // Arrange
      final _initialAndExpectedValueMap = <double, String>{
        0: '0',
        35: '35',
        -45: '-45',
        100.0: '100',
        0.19: '0.19',
        18.8: '18.8',
        0.20: '0.2',
        123.32432400: '123.324324',
        -23.400: '-23.4',
        null: null
      };

      _initialAndExpectedValueMap.forEach((key, value) {
        final initialValue = key;
        final expectedValue = value;

        // Act
        final actualValue = initialValue.toStringWithoutTrailingZeros();

        // Assert
        expect(actualValue, expectedValue);
      });
    });
  });
}
pasul
  • 1,182
  • 2
  • 12
  • 20
3
String removeTrailingZero(String string) {
  if (!string.contains('.')) {
    return string;
  }
  string = string.replaceAll(RegExp(r'0*$'), '');
  if (string.endsWith('.')) {
    string = string.substring(0, string.length - 1);
  }
  return string;
}

======= testcase below =======

000 -> 000
1230 -> 1230
123.00 -> 123
123.001 -> 123.001
123.00100 -> 123.001
abc000 -> abc000
abc000.0000 -> abc000
abc000.001 -> abc000.001
user3044484
  • 463
  • 5
  • 7
2

To improve on What @John's answer: here is a shorter version.

String formatNumber(double n) {
 return n.toStringAsFixed(0) //removes all trailing numbers after the decimal. 
 }
ombiro
  • 869
  • 1
  • 12
  • 19
2

This function removes all trailing commas. It also makes it possible to specify a maximum number of digits after the comma.

   extension ToString on double {
      String toStringWithMaxPrecision({int? maxDigits}) {
        if (round() == this) {
          return round().toString();
        } else {
          if (maxDigits== null) {
            return toString().replaceAll(RegExp(r'([.]*0)(?!.*\d)'), "");
          } else {
            return toStringAsFixed(maxDigits)
                .replaceAll(RegExp(r'([.]*0)(?!.*\d)'), "");
          }
        }
      }
    }
//output without maxDigits: 
// 1.0 -> 1
// 1.0000 -> 1
// 0.99990 -> 0.9999
// 0.103 -> 0.103
//
////output with maxDigits of 2: 
// 1.0 -> 1
// 1.0000 -> 1
// 0.99990 -> 0.99
// 0.103 -> 0.1
1

Here is a very simple way. Using if else I will check if the number equals its integer or it is a fraction and take action accordingly

num x = 24/2; // returns 12.0
num y = 25/2; // returns 12.5

if (x == x.truncate()) {
// it is true in this case so i will do something like
x = x.toInt();
}
batman2020
  • 31
  • 6
1

"Production ready"

extension MeineVer on double {
  String get toMoney => '$removeTrailingZeros₺';
  String get removeTrailingZeros {
    // return if complies to int
    if (this % 1 == 0) return toInt().toString();
    // remove trailing zeroes
    String str = '$this'.replaceAll(RegExp(r'0*$'), '');
    // reduce fraction max length to 2
    if (str.contains('.')) {
      final fr = str.split('.');
      if (2 < fr[1].length) {
        str = '${fr[0]}.${fr[1][0]}${fr[1][1]}';
      }
    }
    return str;
  }
}
23.1250 => 23.12
23.0130 => 23.01
23.1300 => 23.13
23.2000 => 23.2
23.0000 => 23
print(23.1300.removeTrailingZeros) => 23.13
print(23.1300.toMoney) => 23.13₺
Mehmet Filiz
  • 608
  • 5
  • 18
0

user3044484's version with Dart extension:

extension StringRegEx on String {
  String removeTrailingZero() {
    if (!this.contains('.')) {
      return this;
    }

    String trimmed = this.replaceAll(RegExp(r'0*$'), '');
    if (!trimmed.endsWith('.')) {
      return trimmed;
    }

    return trimmed.substring(0, this.length - 1);
  }
}
Walter
  • 1
  • 1
0
// The syntax is same as toStringAsFixed but this one removes trailing zeros
// 1st toStringAsFixed() is executed to limit the digits to your liking
// 2nd toString() is executed to remove trailing zeros

extension Ex on double {
  String toStringAsFixedNoZero(int n) =>            
  double.parse(this.toStringAsFixed(n)).toString(); 
}

// It works in all scenarios. Usage

void main() {

  double length1 = 25.001; 
  double length2 = 25.5487000; 
  double length3 = 25.10000;
  double length4 = 25.0000;
  double length5 = 0.9;

  print('\nlength1= ' + length1.toStringAsFixedNoZero(3));
  print('\nlength2= ' + length2.toStringAsFixedNoZero(3));
  print('\nlenght3= ' + length3.toStringAsFixedNoZero(3));
  print('\nlenght4= ' + length4.toStringAsFixedNoZero(3));
  print('\nlenght5= ' + length5.toStringAsFixedNoZero(0)); 

}

// output:

// length1= 25.001
// length2= 25.549
// lenght3= 25.1
// lenght4= 25
// lenght5= 1
JhorAVi
  • 19
  • 2
0

you can do a simple extension on the double class and add a function which in my case i called it neglectFractionZero()

in this extension function on double(which returns a string) i split the converted number to string and i check if the split part of the string is "0" , if so i return the first part only of the split and i neglect this zero

you can modify it according to your needs

extension DoubleExtension on double { String neglectFractionZero() {

    return toString().split(".").last == "0"? toString().split(".").first:toString();
  }
}
  • Remember that Stack Overflow isn't just intended to solve the immediate problem, but also to help future readers find solutions to similar problems, which requires understanding the underlying code. This is especially important for members of our community who are beginners, and not familiar with the syntax. Given that, **can you [edit] your answer to include an explanation of what you're doing** and why you believe it is the best approach? – Jeremy Caney Feb 22 '22 at 00:42
0

The toString() already removes the useless "0" unless it is "1.0". So you just have to remove ".0" if it ends with that.

regex \.0$

for (var e in <double>[
  1,
  10,
  10.0,
  10.00,
  10.1,
  10.10,
  10.01,
  10.010,
]) {
  print(e.toString().replaceAll(RegExp(r'\.0$'), ''));
}

result:

1
10
10
10
10.1
10.1
10.01
10.01
lsaudon
  • 1,263
  • 11
  • 24
0

String formatWithoutTrailingZeros(double n) {
   return n.toString().replaceFirst(RegExp(r'(?<=\.\d*)(0+$)|(\.0+$)'), '');
}

Explenation:

(?<=\.\d*)(0+$) - Match zeros at the end of a decimal number like 1.040 or 0.00600

(\.0+$) - Match zeros and comma at the end of a decimal number like 1 .00 or 10‎‎‎‎‎‎‎‎‏‏‎ .0

Robbendebiene
  • 4,215
  • 3
  • 28
  • 35
0
void main(List<String> args) {
  print(f('0'));
  print(f('0.0'));
  print(f('12'));
  print(f('12.0'));
  print(f('12.5'));
  print(f('12.5000'));
}

String f(String s) {
  var sepCount = 0;
  return switch (String.fromCharCodes(s.codeUnits.reversed
      .skipWhile((c) => c == 0x30)
      .skipWhile((c) => c == 0x2e && sepCount++ == 0)
      .toList()
      .reversed)) {
    '' => '0',
    final r => r,
  };
}

Output:

0
0
12
12
12.5
12.5
mezoni
  • 10,684
  • 4
  • 32
  • 54
0

One way is good, but 25 ways is better.
Another way to remove trailing zeros.

import 'package:parser_combinator/parser/delimited.dart';
import 'package:parser_combinator/parser/digit1.dart';
import 'package:parser_combinator/parser/eof.dart';
import 'package:parser_combinator/parser/not.dart';
import 'package:parser_combinator/parser/preceded.dart';
import 'package:parser_combinator/parser/replace_all.dart';
import 'package:parser_combinator/parser/skip_while1.dart';
import 'package:parser_combinator/parser/tag.dart';
import 'package:parser_combinator/parser/terminated.dart';
import 'package:parser_combinator/parsing.dart';

void main(List<String> args) {
  final list = [
    '',
    '0',
    '0.0',
    '10.0000000000000000000',
    '10.0000000000000000001'
  ];
  for (final element in list) {
    print(convert1(element));
    print(convert2(element));
  }
}

String convert1(String s) {
  const trailingZeros = Terminated(
    Preceded(
      Tag('.'),
      SkipWhile1(_isZero),
    ),
    Eof(),
  );
  const p = ReplaceAll(trailingZeros, _replace);
  return parseString(p.parse, s);
}

String convert2(String s) {
  const trailingZeros = Delimited(
    Tag('.'),
    SkipWhile1(_isZero),
    Not(Digit1()),
  );

  const p = ReplaceAll(trailingZeros, _replace);
  return parseString(p.parse, s);
}

bool _isZero(int c) => c == 0x30;

String _replace(String s) => '';

Output:

0
0
0
0
10
10
10.0000000000000000001
10.0000000000000000001
mezoni
  • 10,684
  • 4
  • 32
  • 54
-1

I've came up with improved version of @John.

static String getDisplayPrice(double price) {
    price = price.abs();
    final str = price.toStringAsFixed(price.truncateToDouble() == price ? 0 : 2);
    if (str == '0') return '0';
    if (str.endsWith('.0')) return str.substring(0, str.length - 2);
    if (str.endsWith('0')) return str.substring(0, str.length -1);
    return str;
  }

// 10 -> 10
// 10.0 -> 10
// 10.50 -> 10.5
// 10.05 -> 10.05
// 10.000000000005 -> 10
-2
void main() {
  double x1 = 12.0;
  double x2 = 12.5;
  String s1 = x1.toString().trim();
  String s2 = x2.toString().trim();
  print('s1 is $s1 and s2 is $s2');
  }

try trim method https://api.dartlang.org/stable/2.2.0/dart-core/String/trim.html

Rishabh
  • 2,410
  • 4
  • 17
  • 36