{"id":250,"date":"2010-10-14T19:18:43","date_gmt":"2010-10-14T19:18:43","guid":{"rendered":"https:\/\/blogs.mathworks.com\/loren\/2010\/10\/14\/how-many-digits-to-write\/"},"modified":"2010-10-14T12:40:11","modified_gmt":"2010-10-14T12:40:11","slug":"how-many-digits-to-write","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/loren\/2010\/10\/14\/how-many-digits-to-write\/","title":{"rendered":"How Many Digits to Write?"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <introduction>\r\n      <p>Recently, my colleague <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/authors\/35927\">Rob Comer<\/a> and I were talking about how to write out a number, in decimal, so that if it were read back into MATLAB, would retain its\r\n         full precision. The question is how many digits to write out.  The number depends on several things, including the datatype\r\n         the value is stored in.  In addition, it may depend on the precision of the value - i.e., was it data collected during an\r\n         experiment in which only two significant figures were recorded? Today I'll post about the solution Rob and I came up with\r\n         for choosing the number of digits so if you write out the data as a string, you can read it back in to MATLAB with full precision\r\n         retained.\r\n      <\/p>\r\n   <\/introduction>\r\n   <h3>Contents<\/h3>\r\n   <div>\r\n      <ul>\r\n         <li><a href=\"#1\">Create Some Values<\/a><\/li>\r\n         <li><a href=\"#2\">Figure Out Number of Digits<\/a><\/li>\r\n         <li><a href=\"#4\">Number of Digits<\/a><\/li>\r\n         <li><a href=\"#9\">Convert to a Function<\/a><\/li>\r\n         <li><a href=\"#10\">Try Some Values<\/a><\/li>\r\n         <li><a href=\"#11\">Some Magic Now<\/a><\/li>\r\n         <li><a href=\"#14\">How Do You Control Printed Digits?<\/a><\/li>\r\n      <\/ul>\r\n   <\/div>\r\n   <h3>Create Some Values<a name=\"1\"><\/a><\/h3>\r\n   <p>Let's first create some values, both <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2010b\/techdoc\/ref\/single.html\"><tt>single<\/tt><\/a> and <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2010b\/techdoc\/ref\/double.html\"><tt>double<\/tt><\/a> versions of <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2010b\/techdoc\/ref\/pi.html\"><tt>pi<\/tt><\/a>.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">format <span style=\"color: #A020F0\">long<\/span> <span style=\"color: #A020F0\">g<\/span>\r\ndblpi = pi\r\nsnglpi = single(pi)<\/pre><pre style=\"font-style:oblique\">dblpi =\r\n          3.14159265358979\r\nsnglpi =\r\n         3.141593\r\n<\/pre><h3>Figure Out Number of Digits<a name=\"2\"><\/a><\/h3>\r\n   <p>To figure out the number of digits to print, we need to know what the floating point accuracy, sometimes called <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2010b\/techdoc\/ref\/eps.html\"><tt>eps<\/tt><\/a> for the number of interest.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">eps(snglpi)\r\neps(dblpi)<\/pre><pre style=\"font-style:oblique\">ans =\r\n    2.384186e-007\r\nans =\r\n     4.44089209850063e-016\r\n<\/pre><p>As makes sense, we can see that the accuracy of the single precision value is larger than that for the \"equivalent\" double\r\n      precision value. That means that the number next closest to the single precision value is farther away than the number next\r\n      closest to the double precision value.\r\n   <\/p>\r\n   <h3>Number of Digits<a name=\"4\"><\/a><\/h3>\r\n   <p>We can use <tt>eps(x)<\/tt> to help us figure out how many digits to print after the decimal place.  First find total number of digits, base 10:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">log10(eps(snglpi))\r\nlog10(eps(dblpi))<\/pre><pre style=\"font-style:oblique\">ans =\r\n         -6.62266\r\nans =\r\n          -15.352529778863\r\n<\/pre><p>To get to a positive number of digits, simply negate the results.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">-log10(eps(snglpi))\r\n-log10(eps(dblpi))<\/pre><pre style=\"font-style:oblique\">ans =\r\n          6.62266\r\nans =\r\n           15.352529778863\r\n<\/pre><p>And round up to get make sure we don't miss any accuracy.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">ceil(-log10(eps(snglpi)))\r\nceil(-log10(eps(dblpi)))<\/pre><pre style=\"font-style:oblique\">ans =\r\n     7\r\nans =\r\n    16\r\n<\/pre><p>Let's convert the results to a string.  We are taking advantage of the ability to control the number of digits using <tt>*<\/tt> in <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2010b\/techdoc\/ref\/sprintf.html\"><tt>sprintf<\/tt><\/a>.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">snglpistr = sprintf(<span style=\"color: #A020F0\">'%.*f'<\/span>, ceil(-log10(eps(snglpi))), snglpi)\r\ndblpistr = sprintf(<span style=\"color: #A020F0\">'%.*f'<\/span>, ceil(-log10(eps(dblpi))), dblpi)<\/pre><pre style=\"font-style:oblique\">snglpistr =\r\n3.1415927\r\ndblpistr =\r\n3.1415926535897931\r\n<\/pre><p>Now we've captured each value so if written out as a string, and read back into MATLAB, the accuracy is preserved.<\/p>\r\n   <h3>Convert to a Function<a name=\"9\"><\/a><\/h3>\r\n   <p>Taking what we know for finding the number of digits, let's make a function that we can use to test it out.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">digits = @(x) ceil(-log10(eps(x)));\r\nprintdigs = @(x) sprintf(<span style=\"color: #A020F0\">'%.*f'<\/span>, digits(x), x);<\/pre><h3>Try Some Values<a name=\"10\"><\/a><\/h3><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">printdigs(pi)\r\nprintdigs(2\/3)\r\nprintdigs(1000*pi)\r\nprintdigs(pi\/1000)<\/pre><pre style=\"font-style:oblique\">ans =\r\n3.1415926535897931\r\nans =\r\n0.6666666666666666\r\nans =\r\n3141.5926535897929\r\nans =\r\n0.0031415926535897933\r\n<\/pre><h3>Some Magic Now<a name=\"11\"><\/a><\/h3>\r\n   <p>Rob created the necessary magic for getting rid of trailing zeros after the decimal point, while leaving at least one digit\r\n      to the right of the decimal.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">x = 1\/2000\r\nstr = printdigs(x)\r\nstrout = stripzeros(str)<\/pre><pre style=\"font-style:oblique\">x =\r\n                    0.0005\r\nstr =\r\n0.0005000000000000000\r\nstrout =\r\n0.0005\r\n<\/pre><p>Let's try some more values. First create a function to help us again.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">strippedStringValues = @(x) stripzeros(printdigs(x));\r\nvals = [ 100\/289, -1\/17, 1\/2000, 0, 500 -200, 123.4567]\r\n<span style=\"color: #0000FF\">for<\/span> k = vals\r\n    strippedStringValues(k)\r\n<span style=\"color: #0000FF\">end<\/span><\/pre><pre style=\"font-style:oblique\">vals =\r\n  Columns 1 through 2\r\n         0.346020761245675       -0.0588235294117647\r\n  Columns 3 through 4\r\n                    0.0005                         0\r\n  Columns 5 through 6\r\n                       500                      -200\r\n  Column 7\r\n                  123.4567\r\nans =\r\n0.34602076124567471\r\nans =\r\n-0.058823529411764705\r\nans =\r\n0.0005\r\nans =\r\n0.0\r\nans =\r\n500.0\r\nans =\r\n-200.0\r\nans =\r\n123.4567\r\n<\/pre><p>Here's the magic code for stripping the zeros, for those who are interested.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">dbtype <span style=\"color: #A020F0\">stripzeros<\/span><\/pre><pre style=\"font-style:oblique\">\r\n1     function str = stripzeros(strin)\r\n2     %STRIPZEROS Strip trailing zeros, leaving one digit right of decimal point.\r\n3     % Remove trailing zeros while leaving at least one digit to the right of\r\n4     % the decimal place.\r\n5     \r\n6     %   Copyright 2010 The MathWorks, Inc.\r\n7     \r\n8     str = strin;\r\n9     n = regexp(str,'\\.0*$');\r\n10    if ~isempty(n)\r\n11        % There is nothing but zeros to the right of the decimal place;\r\n12        % the value in n is the index of the decimal place itself.\r\n13        % Remove all trailing zeros except for the first one.\r\n14        str(n+2:end) = [];\r\n15    else\r\n16        % There is a non-zero digit to the right of the decimal place.\r\n17        m = regexp(str,'0*$');\r\n18        if ~isempty(m)\r\n19            % There are trailing zeros, and the value in m is the index of\r\n20            % the first trailing zero. Remove them all.\r\n21            str(m:end) = [];\r\n22        end\r\n23    end\r\n\r\n<\/pre><h3>How Do You Control Printed Digits?<a name=\"14\"><\/a><\/h3>\r\n   <p>Are you able to just use the default printing from MATLAB for your values?  Do you use <tt>disp<\/tt>, leave off the semi-colon (<tt>;<\/tt>), use one of the <tt>*printf<\/tt> functions?  What customizations do you need to make to print out values?  Let me know <a href=\"https:\/\/blogs.mathworks.com\/loren\/?p=250#respond\">here<\/a>.\r\n   <\/p><script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_22c380fe109c4777bdd78058a338851c() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='22c380fe109c4777bdd78058a338851c ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 22c380fe109c4777bdd78058a338851c';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        author = 'Loren Shure';\r\n        copyright = 'Copyright 2010 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add author and copyright lines at the bottom if specified.\r\n        if ((author.length > 0) || (copyright.length > 0)) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (author.length > 0) {\r\n                d.writeln('% _' + author + '_');\r\n            }\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n      \r\n      d.title = title + ' (MATLAB code)';\r\n      d.close();\r\n      }   \r\n      \r\n-->\r\n<\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_22c380fe109c4777bdd78058a338851c()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n            the MATLAB code \r\n            <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; 7.11<br><\/p>\r\n<\/div>\r\n<!--\r\n22c380fe109c4777bdd78058a338851c ##### SOURCE BEGIN #####\r\n%% How Many Digits to Write?\r\n% Recently, my colleague\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/authors\/35927 Rob\r\n% Comer> and I were talking about how to write out a number, in decimal, so\r\n% that if it were read back into MATLAB, would retain its full precision.\r\n% The question is how many digits to write out.  The number depends on\r\n% several things, including the datatype the value is stored in.  In\r\n% addition, it may depend on the precision of the value - i.e., was it data\r\n% collected during an experiment in which only two significant figures were\r\n% recorded? Today I'll post about the solution Rob and I came up with for\r\n% choosing the number of digits so if you write out the data as a string,\r\n% you can read it back in to MATLAB with full precision retained.\r\n%% Create Some Values\r\n% Let's first create some values, both\r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2010b\/techdoc\/ref\/single.html\r\n% |single|> and\r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2010b\/techdoc\/ref\/double.html\r\n% |double|> versions of\r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2010b\/techdoc\/ref\/pi.html |pi|>.\r\nformat long g\r\ndblpi = pi\r\nsnglpi = single(pi)\r\n\r\n%% Figure Out Number of Digits\r\n% To figure out the number of digits to print, we need to know what\r\n% the floating point accuracy, sometimes called \r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2010b\/techdoc\/ref\/eps.html\r\n% |eps|> for the number of interest.\r\neps(snglpi) \r\neps(dblpi)\r\n%%\r\n% As makes sense, we can see that the accuracy of the single precision\r\n% value is larger than that for the \"equivalent\" double precision value.\r\n% That means that the number next closest to the single precision value is\r\n% farther away than the number next closest to the double precision value.\r\n%% Number of Digits\r\n% We can use |eps(x)| to help us figure out how many digits to print after\r\n% the decimal place.  First find total number of digits, base 10:\r\nlog10(eps(snglpi))\r\nlog10(eps(dblpi))\r\n%%\r\n% To get to a positive number of digits, simply negate the results.\r\n-log10(eps(snglpi))\r\n-log10(eps(dblpi))\r\n%%\r\n% And round up to get make sure we don't miss any accuracy.\r\nceil(-log10(eps(snglpi)))\r\nceil(-log10(eps(dblpi)))\r\n%%\r\n% Let's convert the results to a string.  We are taking advantage of the\r\n% ability to control the number of digits using |*| in\r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2010b\/techdoc\/ref\/sprintf.html\r\n% |sprintf|>.\r\nsnglpistr = sprintf('%.*f', ceil(-log10(eps(snglpi))), snglpi)\r\ndblpistr = sprintf('%.*f', ceil(-log10(eps(dblpi))), dblpi)\r\n%%\r\n% Now we've captured each value so if written out as a string, and read\r\n% back into MATLAB, the accuracy is preserved.\r\n%% Convert to a Function\r\n% Taking what we know for finding the number of digits, let's make a\r\n% function that we can use to test it out.\r\ndigits = @(x) ceil(-log10(eps(x)));\r\nprintdigs = @(x) sprintf('%.*f', digits(x), x);\r\n%% Try Some Values\r\nprintdigs(pi)\r\nprintdigs(2\/3)\r\nprintdigs(1000*pi)\r\nprintdigs(pi\/1000)\r\n%% Some Magic Now\r\n% Rob created the necessary magic for getting rid of trailing zeros after\r\n% the decimal point, while leaving at least one digit to the right of the\r\n% decimal.\r\nx = 1\/2000\r\nstr = printdigs(x)\r\nstrout = stripzeros(str)\r\n%% \r\n% Let's try some more values. First create a function to help us again.\r\nstrippedStringValues = @(x) stripzeros(printdigs(x));\r\nvals = [ 100\/289, -1\/17, 1\/2000, 0, 500 -200, 123.4567]\r\nfor k = vals\r\n    strippedStringValues(k)\r\nend\r\n%% \r\n% Here's the magic code for stripping the zeros, for those who are\r\n% interested.\r\ndbtype stripzeros\r\n%% How Do You Control Printed Digits?\r\n% Are you able to just use the default printing from MATLAB for your\r\n% values?  Do you use |disp|, leave off the semi-colon (|;|), use one of\r\n% the |*printf| functions?  What customizations do you need to make to\r\n% print out values?  Let me know\r\n% <https:\/\/blogs.mathworks.com\/loren\/?p=250#respond here>.\r\n\r\n##### SOURCE END ##### 22c380fe109c4777bdd78058a338851c\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   \r\n      Recently, my colleague Rob Comer and I were talking about how to write out a number, in decimal, so that if it were read back into MATLAB, would retain its\r\n         full precision.... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/loren\/2010\/10\/14\/how-many-digits-to-write\/\">read more >><\/a><\/p>","protected":false},"author":39,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[26,2],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/250"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/users\/39"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/comments?post=250"}],"version-history":[{"count":0,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/250\/revisions"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/media?parent=250"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/categories?post=250"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/tags?post=250"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}