mathjs icon indicating copy to clipboard operation
mathjs copied to clipboard

`math.format()` and trailing zeros after decimal point in fixed notation

Open balintbrews opened this issue 4 years ago • 4 comments

When precision is set to a value larger than 0, math.format() with the fixed notation appends trailing zeros after the decimal point when the value is an integer: https://github.com/josdejong/mathjs/blob/develop/src/utils/number.js#L353.

Would you be open to a new option to disable this behavior? I tried doing this with a custom format callback, but I quickly ended up copy-pasting hundreds of lines from the library code, because I also didn't want to lose the lots of great things math.format() is doing.

I would be happy to work on a PR to introduce a new option if you think it's a good idea.

What I'm after is exactly what the fixed notation gives me, but I would like to skip adding zeros to integers when I have the precision set to, say, 2, which will give me nicely rounded values after the decimal point. Currently the closest I can get to this is leaving the notation to use auto and set high enough lowerExp and upperExp values. This removes trailing zeros, but due to the different behavior of precision with this notation I can't do rounding only for decimal digits.

balintbrews avatar Jan 11 '21 10:01 balintbrews

There are a lot of different combinations of user needs for either significant digits, digits after the comma, trailing zeros or not, etc. The function math.format can handle many of them nicely but there is indeed still cases that are not easy to address.

I think causes are:

  • precision means significant digits in most notations and digits after the comma in fixed notation.
  • There is not an explicit option to specify whether or not you want trailing zeros, that is simply applied for some

What do you think would be a good solution? Introduce a new option trailingZeros: boolean?

A simple workaround would be to write a little regular expression to strip trailing zeros.

josdejong avatar Jan 16 '21 10:01 josdejong

What do you think would be a good solution? Introduce a new option trailingZeros: boolean?

That would be nice. I just ran into the same issue and I think currently the only solution is to either use a third-party module, or write a custom function that strips the trailing zeros.

PaulRBerg avatar Sep 25 '21 16:09 PaulRBerg

Sharing the solution I ended up creating, for posterity:

import { Decimal } from "decimal.js";

declare module "decimal.js" {
  interface Decimal {
    toFixedWithNoTrailingZeros(): string;
  }
}

// See https://stackoverflow.com/a/65172703/3873510
Decimal.prototype.toFixedWithNoTrailingZeros = function (decimals = 18) {
  return this.toFixed(decimals).replace(/(\.0*|(?<=(\..*))0*)$/, "");
};

Which you use like this:

const result = bignumber!("3.1400");
console.log(result.toFixedWithNoTrailingZeros());

PaulRBerg avatar Sep 25 '21 19:09 PaulRBerg

Thanks for sharing your solution Paul 👍

josdejong avatar Oct 02 '21 08:10 josdejong