); How...">

Round positive doubled to two decimal places in C

As a rule, rounding to 2 decimal places is very simple with

printf("%.2lf",<variable>); 

However, the rounding system is usually rounded to the nearest even . For instance,

 2.554 -> 2.55 2.555 -> 2.56 2.565 -> 2.56 2.566 -> 2.57 

And I want to make sure

 2.555 -> 2.56 2.565 -> 2.57 

In fact, half-life rounding is done in C, but only for Integer;

 int a = (int)(b+0.5) 

So, I ask how to do the same as above, with 2 decimal places for positive values ​​instead of Integer to achieve what I said earlier for printing .

+6
source share
3 answers

It is unclear whether you really want to “round half” or rather “round half from zero,” which requires different handling of negative values.

A single precision binary float accurate to at least 6 decimal places and 20 for double , so pushing the FP value by DBL_EPSILON (defined in float.h) will round up to the next 100th number printf( "%.2lf", x ) for the values n.nn5. without affecting the displayed value for values, not n.nn5

 double x2 = x * (1 + DBL_EPSILON) ; // round half-away from zero printf( "%.2lf", x2 ) ; 

For different types of rounding:

 double x2 = x * (1 - DBL_EPSILON) ; // round half-toward zero double x2 = x + DBL_EPSILON ; // round half-up double x2 = x - DBL_EPSILON ; // round half-down 
+2
source

[Edit] The OP clarified that only the printed value requires rounding to 2 decimal places.

The observation by the OP that rounding off half-way numbers for “round to even” or “rounding from zero” is misleading. Of the 100 "half" numbers, such as 0.005, 0.015, 0.025, ... 0.995, only 4 are usually exactly halfway: 0.125, 0.375, 0.625, 0.875. This is because the floating point format uses base-2, and numbers like 2.565 cannot be represented exactly.

Instead, example numbers, such as 2.565 , have the closest double value 2.564999999999999947... , assuming binary64 . Rounding this number to the nearest 0.01 should be 2.56, not 2.57 as desired by the OP.

Thus, only numbers ending in 0.125 and 0.625 are located halfway and rounded, and not upward at the request of the OP. Suggest accepting this and using:

 printf("%.2lf",variable); // This should be sufficient 

To get closer to the OP goal, the numbers can be A) tested against the end of 0.125 or 0.625 or B) slightly increased. Smallest increase would be

 #include <math.h> printf("%.2f", nextafter(x, 2*x)); 

Another pushing method is found with @Clifford.


[Former answer that rounds a double to the nearest double multiple of 0.01]

A typical floating point uses formats such as binary64 , which uses base-2. "Rounding to the nearest mathematical 0.01 and links from 0.0" is complicated.

As @Pascal Cuoq mentions, floating point numbers like 2.555 are usually only close to 2.555 and have a more accurate value, like 2.555000000000000159872... which is not half.

@BLUEPIXY's solution is the best and practical.

 x = round(100.0*x)/100.0; 

"Round functions round off their argument to the nearest integer value in a floating point format, rounding half the cases from zero, regardless of the current direction of rounding." C11dr §7.12.9.6.

The ((int)(100 * (x + 0.005)) / 100.0) approach has two problems: it can rotate in the wrong direction for negative numbers (the OP did not specify), and integers usually have a much smaller range ( INT_MIN - INT_MAX ), which is double .


There are some more cases when, when double x = atof("1.115"); , which ends around 1.12, when it really should be 1.11 , because 1.115 , because double really closer to 1.11 , not halfway. "

 string x rounded x 1.115 1.1149999999999999911182e+00 1.1200000000000001065814e+00 

The OP did not indicate rounding of negative numbers, assuming y = -f(-x) .

+1
source

Below is the exact code for rounding a double to the nearest 0.01 double .

Code functions such as x = round(100.0*x)/100.0; , besides what it processes, uses manipulations to ensure scaling to 100.0, it is executed precisely without loss of accuracy.

This is most likely more code than the OP is interested in, but it works.

It works for the entire range double -DBL_MAX to DBL_MAX . (you still need to test more units).
It depends on FLT_RADIX == 2 , which is common.

 #include <float.h> #include <math.h> void r100_best(const char *s) { double x; sscanf(s, "%lf", &x); // Break x into whole number and fractional parts. // Code only needs to round the fractional part. // This preserves the entire `double` range. double xi, xf; xf = modf(x, &xi); // Multiply the fractional part by N (256). // Break into whole and fractional parts. // This provides the needed extended precision. // N should be >= 100 and a power of 2. // The multiplication by a power of 2 will not introduce any rounding. double xfi, xff; xff = modf(xf * 256, &xfi); // Multiply both parts by 100. // *100 incurs 7 more bits of precision of which the preceding code // insures the 8 LSbit of xfi, xff are zero. int xfi100, xff100; xfi100 = (int) (xfi * 100.0); xff100 = (int) (xff * 100.0); // Cast here will truncate (towards 0) // sum the 2 parts. // sum is the exact truncate-toward-0 version of xf*256*100 int sum = xfi100 + xff100; // add in half N if (sum < 0) sum -= 128; else sum += 128; xf = sum / 256; xf /= 100; double y = xi + xf; printf("%6s %25.22f ", "x", x); printf("%6s %25.22f %.2f\n", "y", y, y); } int main(void) { r100_best("1.105"); r100_best("1.115"); r100_best("1.125"); r100_best("1.135"); r100_best("1.145"); r100_best("1.155"); r100_best("1.165"); return 0; } 
+1
source

Source: https://habr.com/ru/post/973275/


All Articles