Extra Leading Zeros When Printing Float Using Printf

Extra leading zeros when printing float using printf?

With the %f format specifier, the "2" is treated as the minimum number of characters altogether, not the number of digits before the decimal dot. Thus you have to replace it with 4 to get two leading digits + the decimal point + one decimal digit.

printf("%d:%02d:%04.1f hours\n", 1, 4, 2.123456);

printf' with leading zeros in C

Your format specifier is incorrect. From the printf() man page on my machine:

0 A zero '0' character indicating that zero-padding should be used rather than blank-padding. A '-' overrides a '0' if both are used;

Field Width:
An optional digit string specifying a field width; if the output string has fewer characters than the field width it will be blank-padded on the left (or right, if the left-adjustment indicator has been given) to make up the field width (note that a leading zero is a flag, but an embedded zero is part of a field width);

Precision: An optional period, '.', followed by an optional digit string giving a precision which specifies the number of digits to appear after the decimal point, for e and f formats, or the maximum number of characters to be printed from a string; if the digit string is missing, the precision is treated as zero;

For your case, your format would be %09.3f:

#include <stdio.h>

int main(int argc, char **argv)
{
printf("%09.3f\n", 4917.24);
return 0;
}

Output:

$ make testapp
cc testapp.c -o testapp
$ ./testapp
04917.240

Note that this answer is conditional on your embedded system having a printf() implementation that is standard-compliant for these details - many embedded environments do not have such an implementation.

printf how to do floating points with leading zeros

Try this printf (C, Perl, PHP) format string:

"%07.2f"

Printing leading 0's in C

printf("%05d", zipCode);

The 0 indicates what you are padding with and the 5 shows the width of the integer number.

Example 1: If you use "%02d" (useful for dates) this would only pad zeros for numbers in the ones column. E.g., 06 instead of 6.

Example 2: "%03d" would pad 2 zeros for one number in the ones column and pad 1 zero for a number in the tens column. E.g., number 7 padded to 007 and number 17 padded to 017.

Avoid trailing zeroes in printf()

This can't be done with the normal printf format specifiers. The closest you could get would be:

printf("%.6g", 359.013); // 359.013
printf("%.6g", 359.01); // 359.01

but the ".6" is the total numeric width so

printf("%.6g", 3.01357); // 3.01357

breaks it.

What you can do is to sprintf("%.20g") the number to a string buffer then manipulate the string to only have N characters past the decimal point.

Assuming your number is in the variable num, the following function will remove all but the first N decimals, then strip off the trailing zeros (and decimal point if they were all zeros).

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 >= 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';
}
}
}

If you're not happy with the truncation aspect (which would turn 0.12399 into 0.123 rather than rounding it to 0.124), you can actually use the rounding facilities already provided by printf. You just need to analyse the number before-hand to dynamically create the widths, then use those to turn the number into a string:

#include <stdio.h>

void nDecimals (char *s, double d, int n) {
int sz; double d2;

// Allow for negative.

d2 = (d >= 0) ? d : -d;
sz = (d >= 0) ? 0 : 1;

// Add one for each whole digit (0.xx special case).

if (d2 < 1) sz++;
while (d2 >= 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 < sizeof(num)/sizeof(*num); i++) {
nDecimals (str, num[i], 3);
printf ("%30.20f -> %s\n", num[i], str);
}
return 0;
}

The whole point of nDecimals() 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 main() shows this in action:

  40.00000000000000000000 -> 40.000
359.01335000000000263753 -> 359.013
-359.00999000000001615263 -> -359.010
359.00999999999999090505 -> 359.010
3.01357000000000008200 -> 3.014
0.11111111099999999852 -> 0.111
1.12233439999999995429 -> 1.122

Once you have the correctly rounded value, you can once again pass that to morphNumericString() to remove trailing zeros by simply changing:

nDecimals (str, num[i], 3);

into:

nDecimals (str, num[i], 3);
morphNumericString (str, 3);

(or calling morphNumericString at the end of nDecimals but, in that case, I'd probably just combine the two into one function), and you end up with:

  40.00000000000000000000 -> 40
359.01335000000000263753 -> 359.013
-359.00999000000001615263 -> -359.01
359.00999999999999090505 -> 359.01
3.01357000000000008200 -> 3.014
0.11111111099999999852 -> 0.111
1.12233439999999995429 -> 1.122

How to print a float number without extra zero digits in C

There are many ways to remove the extra zeros.

  1. Easiest way is to use %g as the format specifier in the printf statement. Eg. printf("%g",a/b);. This is remove the extra zeros after the decimal.

  2. You can use printf("%.0d%.4g\n", (int)(a/b)/10, (a/b)-((int)(a/b)-(int)(a/b)%10));.

  3. You can use a separate function to remove the extra zeros but it is a tedious process. First transfer all the digits to a string and remove the unwanted zeros from the end.

  4. You can also use %.2f format specifier to reduce the zeros. Eg. printf("%.2f",a/b); - this can be used where you want to print the exact number of digits after the decimal point. %.<the number of digits to be printed after decimal point>f.

C formatted string - How to add leading zeros to float and int values?

You can zero pad with %08.4f, for example. Note that the first number is the entire field width, not just the number of places you want before the decimal. In your example, the 3 in %3.4 has no effect. If you want your last number to only have three decimal places, you'll want %07.3f for that one.

The %d formats are easier - in your case, just %02d should do it.

How to display multiple leading zeros for floating point values in C++?

A couple of comments have mentioned std::setfill('0') and std::setw. While these are necessary, they're not sufficient to the task. For example, this code:

std::cout << std::setfill('0') << std::setw(7) << std::showpos << 0.012;

will produce: 0+0.012 as its output. This is obviously not quite what we wanted.

We need to add the std::internal flag to tell the stream to insert "internal padding" -- i.e., the padding should be inserted between the sign and the rest of the number, so code like this:

std::cout << std::setfill('0') << std::setw(7) << std::internal << std::showpos << 0.012;

...produces the output we want: +00.012.

Also note that the padding character is "sticky", so if you alternate between using std::setw with numeric and non-numeric types, you'll probably need/want to change it each time. Otherwise, something like std::cout << setw(12) << name; will produce results like: 0000000Jerry, which is rarely desired either.

To assure that we always get the same number of places after the decimal point, we also need to set the std::fixed flag, and specify the number of places with std::setprecision, such as:

#include <iostream>
#include <iomanip>
#include <vector>

int main() {
std::vector<double> values { 0.1234, 1.234, 1.5555 };

for (auto d : values)
std::cout << std::internal << std::showpos << std::setw(9)
<< std::setprecision(3) << std::setfill('0') << d << "\n";
}

Which produces the output I believe is desired:

+0000.123
+0001.234
+0001.556

There is one circumstance under which you won't get aligned results this way though: if you have a number too large to fit into the field provided, all the places before the decimal point will still be printed. For example, if we added 1e10 to the list of numbers to be printed by the preceding code, it would be printed out as: +10000000000.000, which obviously won't align with the rest.

The obvious way to deal with that would be to just put up with it, and if it arises often enough to care about, increase the field size to accommodate the larger numbers.

Another possibility would be to use fixed notation only the number is below a certain threshold, and switch to (for example) scientific notation for larger numbers.

At least in my experience, code like this tends to be used primarily for financial data, in which case the latter option usually isn't acceptable though.

How to hide leading zero in printf

The C standard says that for the f and F floating point format specifiers:

If a decimal-point character appears, at least one digit appears before it.

I think that if you don't want a zero to appear before the decimal point, you'll probably have to do something like use snprintf() to format the number into a string, and remove the 0 if the formatted string starts with "0." (and similarly for "-0."). Then pass that formatted string to our real output. Or something like that.

PHP: How to add leading zeros/zero padding to float via sprintf()?

Short answer: sprintf('%05.2f', 1); will give the desired result 01.00

Note how %02 was replaced by %05.

Explanation

This forum post pointed me in the right direction: The first number does neither denote the number of leading zeros nor the number of total charaters to the left of the decimal seperator but the total number of characters in the resulting string!

Example

sprintf('%02.2f', 1); yields at least the decimal seperator "." plus at least 2 characters for the precision. Since that is already 3 characters in total, the %02 in the beginning has no effect. To get the desired "2 leading zeros" one needs to add the 3 characters for precision and decimal seperator, making it sprintf('%05.2f', 1);

Some code

$num = 42.0815;

function printFloatWithLeadingZeros($num, $precision = 2, $leadingZeros = 0){
$decimalSeperator = ".";
$adjustedLeadingZeros = $leadingZeros + mb_strlen($decimalSeperator) + $precision;
$pattern = "%0{$adjustedLeadingZeros}{$decimalSeperator}{$precision}f";
return sprintf($pattern,$num);
}

for($i = 0; $i <= 6; $i++){
echo "$i max. leading zeros on $num = ".printFloatWithLeadingZeros($num,2,$i)."\n";
}

Output

0 max. leading zeros on 42.0815 = 42.08
1 max. leading zeros on 42.0815 = 42.08
2 max. leading zeros on 42.0815 = 42.08
3 max. leading zeros on 42.0815 = 042.08
4 max. leading zeros on 42.0815 = 0042.08
5 max. leading zeros on 42.0815 = 00042.08
6 max. leading zeros on 42.0815 = 000042.08


Related Topics



Leave a reply



Submit