bugGNU Octave - Bugs: bug #36133, num2str displays more than 16...


bug #36133: num2str displays more than 16 significant digits for large integer inputs

Submitted by:  Rik <rik5>
Submitted on:  Mon 09 Apr 2012 03:08:33 AM UTC  
Category:  Octave Function Severity:  3 - Normal
Priority:  5 - Normal Item Group:  Inaccurate Result
Status:  Confirmed Assigned to:  None
Originator Name:  Open/Closed:  Open
Release:  dev Operating System:  Any

Add a New Comment(Rich Markup)

You are not logged in

Please log in, so followups can be emailed to you.


( Jump to the original submission)

Wed 25 Apr 2018 10:40:52 PM UTC, comment #11:

@Joe: Could you run this additional test and report back the result?

Rik <rik5>
Project Administrator
Wed 25 Apr 2018 09:43:54 PM UTC, comment #10:

Results from Matlab will be interesting, but I doubt that they test that each number to be printed is an exact power of two. There are 1024 of those numbers compared to 2^53 (9e15) numbers representable in the mantissa. It really, really fails the 80/20 rule to worry about them.

According to Matlab's documentation for both sprintf and num2str, they are aware of the issue

Also, according to the documentation for num2str

That's fine, but my guess is that Matlab just uses a form of the %g format for both floating point and integer numbers. Octave, however, tries to switch format based on whether the input is an integer. The code is

I bet changing the integer case would fix some of this.

Rik <rik5>
Project Administrator
Wed 25 Apr 2018 07:44:04 PM UTC, comment #9:

15-17 decimal digits is true for arbitrary numbers, but powers of 2 can be converted to decimal exactly, up to 2^1023. So limiting to 15-17 decimal digits doesn't make sense for ALL 64-bit IEEE floating point values.

But yes, we should be switching to exponential display using some kind of rules that produce "pleasing" results. One problem is deciding what those rules should be.

What does Matlab do for num2str (2^512)? What about sprintf ('%.0f', 2^512)?

Also, if we "clean up" the output form our printf functions, then they will differ from what people will get when they use C++ streams or C stdio functions. Is that really what we want? If so, then we might want to make our functions easily available for use in .oct files.

A related issue is the max precision problem in bug #53456.

John W. Eaton <jwe>
Project Administrator
Wed 25 Apr 2018 04:58:54 PM UTC, comment #8:

Adding in jwe because the behavior is fascinating. From Hartmut's tests in comment #3, the Matlab sprintf function returns

where the '1' in the sectond position is very real.

Octave's answer for the same code is

If I align the two

it seems pretty clear what Matlab has done. First, Octave uses the C library routine for sprintf so we get whatever default behavior is implemented when the precision exceeds that of the underlying number. But Matlab has written a shim layer for sprintf which calls the sprintf library, but then cleans up the result. However, they haven't been too clever about it. IEEE-854 doubles have a variable precision of 15-17 decimal digits. The extra '1' occurs because they are rounding the digit '9' which is the 18 significant figure and not valid.

In any case, once Matlab has printed 17 digits, it pads the rest of the string with zeros. This is pretty easy to do in C++ with the substr() function or operator[] access and a for loop.

So should Octave do something similar? And if so, where should it be done? It could be done just in our sprintf routine, but then other actions like printf would diverge in behavior. That means it would probably be better to do it in octave::stream.

Rik <rik5>
Project Administrator
Wed 25 Apr 2018 04:33:50 PM UTC, comment #7:

@Joe: Are you proposing that the two assert statements be added as BIST tests to num2str.m?

Also, can you determine when Matlab switches from decimal to exponential notation?

Try running this code:

Octave never switches over to exponential notation

Rik <rik5>
Project Administrator
Tue 24 Apr 2018 08:14:15 PM UTC, comment #6:

Oh sorry that's me creating a new one to make sure I don't get confused. I also realized I didn't double check my outputs with Matlab. It my comment should have read:

%! assert (num2str (1e23), "9.999999999999999e+22");
%! assert (num2str (1e25), "1e+25");

Also int2str has the same bug, how can I link that function to this bug?

Joe <spikel46>
Tue 24 Apr 2018 07:42:17 PM UTC, comment #5:

Your code uses num2strE which is not an Octave core function. Try 'which num2strE' to find the location. You will need to report a bug against whoever wrote that function.

Rik <rik5>
Project Administrator
Tue 24 Apr 2018 07:21:35 PM UTC, comment #4:

I think the test should read:

%! assert (num2strE (1e23), "1e+23");
%! assert (num2strE (12345678901234567890), "1.234567890123457e+20");

Also int2str has the same bug, how can I link that function to this bug?

Joe <spikel46>
Mon 21 Nov 2016 01:05:33 PM UTC, comment #3:

Matlab R2014b:

(The second 1 in the first result is real.)

Hartmut <hardy>
Sun 20 Nov 2016 03:17:53 PM UTC, comment #2:

For comparison, could someone try the following in Matlab?

Rik <rik5>
Project Administrator
Sat 19 Nov 2016 09:24:37 PM UTC, comment #1:

This is still present in Octave 4.2.0.

Hartmut <hardy>
Mon 09 Apr 2012 03:08:33 AM UTC, original submission:

Example code:

This should be '1' with 25 zeros after it.

Matlab correctly masks large integer inputs to just 16 significant digits.

For something really wacky try

Rik <rik5>
Project Administrator


(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:

No files currently attached


Depends on the following items: None found

Items that depend on this one: None found


Carbon-Copy List
  • -email is unavailable- added by jwe (Posted a comment)
  • -email is unavailable- added by rik5
  • -email is unavailable- added by spikel46 (Posted a comment)
  • -email is unavailable- added by hardy (Posted a comment)
  • -email is unavailable- added by mtmiller (Updated the item)
  • -email is unavailable- added by rik5 (Submitted the item)

    Do you think this task is very important?
    If so, you can add your encouragement to it.
    This task has 0 encouragements so far.

    Only project members can vote.




    Follow 3 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2018-04-25 rik5 Carbon-Copy- => Added jwe
    2014-01-19 mtmiller CategoryNone => Octave Function
        Operating SystemGNU/Linux => Any

    Back to the top

    Powered by Savane 3.3