Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>This can't be done with the normal <code>printf</code> format specifiers. The closest you could get would be:</p> <pre><code>printf("%.6g", 359.013); // 359.013 printf("%.6g", 359.01); // 359.01 </code></pre> <p>but the ".6" is the <em>total</em> numeric width so</p> <pre><code>printf("%.6g", 3.01357); // 3.01357 </code></pre> <p>breaks it.</p> <p>What you <em>can</em> do is to <code>sprintf("%.20g")</code> the number to a string buffer then manipulate the string to only have N characters past the decimal point.</p> <p>Assuming your number is in the variable num, the following function will remove all but the first <code>N</code> decimals, then strip off the trailing zeros (and decimal point if they were all zeros).</p> <pre><code>char str[50]; sprintf (str,"%.20g",num); // Make the number. morphNumericString (str, 3); : : void morphNumericString (char *s, int n) { char *p; int count; p = strchr (s,'.'); // Find decimal point, if any. if (p != NULL) { count = n; // Adjust for more or less decimals. while (count &gt;= 0) { // Maximum decimals allowed. count--; if (*p == '\0') // If there's less than desired. break; p++; // Next character. } *p-- = '\0'; // Truncate string. while (*p == '0') // Remove trailing zeros. *p-- = '\0'; if (*p == '.') { // If all decimals were zeros, remove ".". *p = '\0'; } } } </code></pre> <hr> <p>If you're not happy with the truncation aspect (which would turn <code>0.12399</code> into <code>0.123</code> rather than rounding it to <code>0.124</code>), you can actually use the rounding facilities already provided by <code>printf</code>. You just need to analyse the number before-hand to dynamically create the widths, then use those to turn the number into a string:</p> <pre><code>#include &lt;stdio.h&gt; void nDecimals (char *s, double d, int n) { int sz; double d2; // Allow for negative. d2 = (d &gt;= 0) ? d : -d; sz = (d &gt;= 0) ? 0 : 1; // Add one for each whole digit (0.xx special case). if (d2 &lt; 1) sz++; while (d2 &gt;= 1) { d2 /= 10.0; sz++; } // Adjust for decimal point and fractionals. sz += 1 + n; // Create format string then use it. sprintf (s, "%*.*f", sz, n, d); } int main (void) { char str[50]; double num[] = { 40, 359.01335, -359.00999, 359.01, 3.01357, 0.111111111, 1.1223344 }; for (int i = 0; i &lt; sizeof(num)/sizeof(*num); i++) { nDecimals (str, num[i], 3); printf ("%30.20f -&gt; %s\n", num[i], str); } return 0; } </code></pre> <p>The whole point of <code>nDecimals()</code> in this case is to correctly work out the field widths, then format the number using a format string based on that. The test harness <code>main()</code> shows this in action:</p> <pre><code> 40.00000000000000000000 -&gt; 40.000 359.01335000000000263753 -&gt; 359.013 -359.00999000000001615263 -&gt; -359.010 359.00999999999999090505 -&gt; 359.010 3.01357000000000008200 -&gt; 3.014 0.11111111099999999852 -&gt; 0.111 1.12233439999999995429 -&gt; 1.122 </code></pre> <p>Once you have the correctly rounded value, you can once again pass that to <code>morphNumericString()</code> to remove trailing zeros by simply changing:</p> <pre><code>nDecimals (str, num[i], 3); </code></pre> <p>into:</p> <pre><code>nDecimals (str, num[i], 3); morphNumericString (str, 3); </code></pre> <p>(or calling <code>morphNumericString</code> at the end of <code>nDecimals</code> but, in that case, I'd probably just combine the two into one function), and you end up with:</p> <pre><code> 40.00000000000000000000 -&gt; 40 359.01335000000000263753 -&gt; 359.013 -359.00999000000001615263 -&gt; -359.01 359.00999999999999090505 -&gt; 359.01 3.01357000000000008200 -&gt; 3.014 0.11111111099999999852 -&gt; 0.111 1.12233439999999995429 -&gt; 1.122 </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload