Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow configurable precision in format when in "engineering" mode #1147

Closed
ewanorr opened this issue Jun 27, 2018 · 11 comments
Closed

Allow configurable precision in format when in "engineering" mode #1147

ewanorr opened this issue Jun 27, 2018 · 11 comments

Comments

@ewanorr
Copy link

ewanorr commented Jun 27, 2018

The "engineering" mode in the format function seems to ignore significant figures that occur after a decimal point. Considering the following two examples, the first performs as expected; however I expected that the second example would be more precise.

format(12400,{notation: "engineering"})
"12.400e+3" // expected "12.400e+3"

format(12400.00,{notation: "engineering"})
"12.400e+3" // expected "12.40000e+3"

@ericman314
Copy link
Collaborator

Unfortunately, math.js does not have any mechanism to keep track of significant figures. In your example, both numbers are converted to the same floating point representation the moment they are encountered.

There's no reason such a feature couldn't be added, which would propagate errors through each calculation and automatically format the result with the correct number of significant figures, but it would be a tremendous undertaking. The decimal.js library, which math.js's BigNumber type is based on, probably comes closest to realizing such a capability.

@ewanorr
Copy link
Author

ewanorr commented Jun 28, 2018

Thank you for your reply, good to know that it is an complex problem and I wasn't missing something obvious. I was hoping that I could get the functionality that I wanted by specifying the precision; however, I am a bit confused about specifying precision when formatting with engineer mode.

When formatting numbers that have zeros that trail a decimal place then it seems that the behaviour of the exponential mode is what I expected; however, for engineering mode the behaviour isn't analogous to that seen in the exponential mode. For instance, compare lines 4 and 9 below.

  1. format(12400, {notation: "exponential"}) -> "1.24e+4"

  2. format(12400.00, {notation: "exponential"}) -> "1.24e+4"

  3. format(12400.00, {notation: "exponential", precision: 4}) -> "1.240e+4"

  4. format(12400.00, {notation: "exponential", precision: 7}) -> "1.240000e+4"

  5. format(12400.00, {notation: "exponential", precision: 8}) -> "1.2400000e+4"

  6. format(12400, {notation: "engineering"}) -> "12.400e+3"

  7. format(12400.00, {notation: "engineering"}) -> "12.400e+3"

  8. format(12400.00, {notation: "engineering", precision: 4}) -> "12.400e+3" // expected 12.40e+3"

  9. format(12400.00, {notation: "engineering", precision: 7}) -> "12.400e+3" // expected 12.40000e+3"

  10. format(12400.00, {notation: "engineering", precision: 8}) -> "12.400e+3" // expected 12.400000e+3"

@ericman314
Copy link
Collaborator

The documentation doesn't actually specify what meaning precision has in engineering mode, so perhaps this is a good time to specify one. I'm with you here: I think it would be good to change it so precision has the same meaning in engineering mode as it does in exponential mode.

Do you have any interest in tackling this yourself?

@harrysarson
Copy link
Collaborator

harrysarson commented Jun 29, 2018

Have changed the title 😄

@harrysarson harrysarson changed the title The "engineering" mode in the format function seems to ignore significant figures Allow configurable precision in format when in "engineering" mode Jun 29, 2018
@josdejong
Copy link
Owner

Thanks for opening this discussions @ewanorr .

It's ok with me to change the behavior of engineering notation. (Will be a breaking change of course).

Maybe instead of using precision everywhere with two different meanings for it (significant figures or numbers behind the decimal point) we should introduce a new option significantFigures besides precision which applies the current behavior of engineering notation.

@ewanorr
Copy link
Author

ewanorr commented Jul 3, 2018

Hi @ericman314 thank you for looking at this. At the moment I probably wouldn't know where to begin with attempting to change the behaviour of engineering notation. If me and one of my colleagues get free time in a few weeks time I might see if he is keen and able to have a look at this with me.

@ericman314
Copy link
Collaborator

No worries, @ewanorr. I'm sure someone here will be happy to take care of it.

@josdejong, looking more closely at the code for engineering mode, it looks like the original intent of engineering mode was to add zeroes if necessary to produce a number with precision significant digits, although where precision comes into play I'm not entirely sure:

mathjs/src/utils/number.js

Lines 267 to 268 in f0e5ed5

// add zeros if necessary (for ex: 1e+8)
if (c.length - 1 < significandsDiff) c = c.concat(zeros(significandsDiff - (c.length - 1)))

Which means in this example from @ewanorr, the expected result is the intended result:

format(12400.00, {notation: "engineering", precision: 7}) 
actual 12.400e+3, expected 12.40000e+3

I checked and there are no tests cases that require adding zeroes, so I think this is a bug that has gone unnoticed a very long time. So I think this would actually be a bug fix and not a breaking change. And to keep things simple, I would be okay with just sticking with the precision option for now. It is true though that JavaScript uses the two functions toFixed and toPrecision for formatting; so it may also be appropriate to use two differently named options depending on whether you are in fixed mode or not, as a breaking change later on.

@ericman314
Copy link
Collaborator

Another thought: we could remove the notation: 'fixed' option entirely, and replace it with fixed: # where # is the number of digits after the decimal point. It could be used with engineering, exponential, or normal mode. Or, you can use precision: # to specify the number of significant figures in any of the engineering, exponential, or normal modes. If both are specified, one would take precedence over the other. This would more closely mirror JavaScript's toFixed and toPrecision functions. This would be a pretty big breaking change, though.

@harrysarson harrysarson added the bug label Jul 4, 2018
@josdejong
Copy link
Owner

@ericman314 I think you're right, the intention was to add trailing zeros to note real significant digits, so this is about a bug in the engineering notation.

I like your proposal to keep precision for significant digits, and create a new fixed for number of digits after the decimal point. We could still keep notation: 'fixed' available though it would be redundant when just specifying fixed: #. I like making these things explicit.

@ericman314
Copy link
Collaborator

I've submitted a PR #1163 which hopefully fixes the bug.

@josdejong
Copy link
Owner

Should be fixed now in v5.0.3, thanks again Eric.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants