Round Off a Double While Maintaining the Trailing Zero

Round off a double while maintaining the trailing zero

This is a printing poblem:

double d = 1.5;
System.out.println(String.format("%.2f", d)); // 1.50

How to round double values but keep trailing zeros

You can create a formatter like this example:

int numDigitsAfterPoint = 5;
double num = 1.25d;
string result = num.ToString("0." + new string('0', numDigitsAfterPoint));

or (more easily)

string result = num.ToString("F" + numDigitsAfterPoint);

As a sidenote, ToString uses the MidpointRounding.AwayFromZero instead of the MidpointRounding.ToEven (also called Banker's Rounding). As an example:

var x1 = 1.25.ToString("F1");
var x2 = 1.35.ToString("F1");
var x3 = Math.Round(1.25, 1).ToString();
var x4 = Math.Round(1.35, 1).ToString();

These will produce different result (because Math.Round normally uses MidpointRounding.ToEven)

And note that internally ToString() seems to do some "magic" before rounding digits. For doubles, if you ask him less than 15 digits, I think it rounds to 15 digits first and then rounds to the right number of digits. See here https://ideone.com/ZBEis9

Rounding a number in Python but keeping ending zeros

As you are talking about trailing zeros, this is a question about representation as string,
you can use

>>> "%.2f" % round(2606.89579999999, 2)
'2606.90'

Or use modern style with format function:

>>> '{:.2f}'.format(round(2606.89579999999, 2))
'2606.90'

and remove point with replace or translate (_ refers to result of previous command in python console):

>>> _.translate(None, '.')
'260690'

Note that rounding is not needed here, as .2f format applyies the same rounding:

>>> "%.2f" % 2606.89579999999
'2606.90'

But as you mentioned excel, you probably would opt to roll your own rounding function, or use decimal, as float.round can lead to strange results due to float representation:

>>> round(2.675, 2)
2.67
>>> round(2606.89579999999, 2)
2606.89

With decimal use quantize:

>>> from decimal import *
>>> x = Decimal('2606.8950000000001')
# Decimal('2606.8950000000001')
>>> '{}'.format(x.quantize(Decimal('.01'), rounding=ROUND_HALF_EVEN))
'2606.90'

That, for your original task, becomes:

>>> x = Decimal('2606.8950000000001')
>>> int((x*100).quantize(1, rounding=ROUND_HALF_EVEN))
260690

And the reason of strange rounding comes to the front with Decimal:

>>> x = Decimal(2606.8950000000001)
# Decimal('2606.89499999999998181010596454143524169921875') # internal float repr

DecimalFormat - Format decimal to preserve variable amount of trailing zeros

"Preserve" trailing zeros?

A double value doesn't know how many trailing zeroes you want to see. It is just a number, and 1.00 and 1.000 are the same number, i.e. the number 1. What you are asking cannot be done with a double value.

Now, BigDecimal does remember the number of trailing zeroes, so if you want to print a BigDecimal value, retaining the scale of the number, but ensuring it never prints in scientific notation, don't use a DecimalFormat, but instead use toPlainString():

Returns a string representation of this BigDecimal without an exponent field.


UPDATE

If you want to print a double value with as many decimal fraction digits as needed (i.e. no trailing zeroes), and want to make sure it never prints in scientific notation, use a DecimalFormat with very high MaximumIntegerDigits and very high setMaximumFractionDigits.

"Very high" means values exceeding the range of a double, so 999 is a good "round" number, though 330 would be high enough.

Test

DecimalFormat fmt = new DecimalFormat("0");
fmt.setMaximumIntegerDigits(330);
fmt.setMaximumFractionDigits(330);

System.out.println("0.0123400 = " + 0.0123400 + " = " + fmt.format(0.0123400));
System.out.println("123400.00 = " + 123400.00 + " = " + fmt.format(123400.00));
System.out.println("NaN = " + Double.NaN + " = " + fmt.format(Double.NaN));
System.out.println("-INFINITY = " + Double.NEGATIVE_INFINITY + " = " + fmt.format(Double.NEGATIVE_INFINITY));
System.out.println("+INFINITY = " + Double.POSITIVE_INFINITY + " = " + fmt.format(Double.POSITIVE_INFINITY));
System.out.println("MIN_NORMAL = " + Double.MIN_NORMAL + " = " + fmt.format(Double.MIN_NORMAL));
System.out.println("MIN_VALUE = " + Double.MIN_VALUE + " = " + fmt.format(Double.MIN_VALUE));
System.out.println("MAX_VALUE = " + Double.MAX_VALUE + " = " + fmt.format(Double.MAX_VALUE));

Output

0.0123400  = 0.01234   = 0.01234
123400.00 = 123400.0 = 123400
NaN = NaN = �
-INFINITY = -Infinity = -∞
+INFINITY = Infinity = ∞
MIN_NORMAL = 2.2250738585072014E-308 = 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072014
MIN_VALUE = 4.9E-324 = 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000049
MAX_VALUE = 1.7976931348623157E308 = 179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

How to round a number and make it show zeros?

We can use format

format(round(a), nsmall = 2)
#[1] "14.00"

As @arvi1000 mentioned in the comments, we may need to specify the digits in round

format(round(a, digits=2), nsmall = 2) 

data

a <- 14.0034

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

Math.Round not keeping the trailing zero

1.4 is the same as 1.40 - you just want to display it differently. Use a format string when calling ToString - like value.ToString("0.00")

Keeping trailing zeros

If this is for printing purposes, sprintf is what you are after:

> sprintf("%.3f", round(5.2,3))
[1] "5.200"

See ?sprintf for formatting details.

Print float/double without trailing zeros?

Use snprintf to print to a temporary buffer then remove the trailing '0' characters manually. There is no other way that's both correct and reasonably easy to implement.

Math.Round, keep decimal place

Numbers don't have any conception of zeroes after a decimal point.

You're actually asking how to convert the number into a string with extra zeroes:

(2.301).ToString("0.00") // "2.30"

See numeric format strings for more detail.

In particular, the 0 specifier will round away from zero.



Related Topics



Leave a reply



Submit