0

49.765 is my output from a ring of commands. I want to use print f to round it by two decimal figures to 49.77.

What is the code for it?

Shawn
  • 7
  • 2
    Please clarify your question: do you mean printf(1) here (the shell command) or printf(3) (the C library function)? My answer below gives the answer for printf(1), which would be on-topic here on Unix.SE. Harshit's answer gives the answer for printf(3), which is really more of a Stack Overflow type of question. – Warren Young Oct 01 '16 at 04:47

3 Answers3

4
$ x=49.765
$ printf "%.2f" $(echo "$x + 0.005" | bc)

You have to use external commands because there is no built-in rounding feature in printf(1), and the POSIX shell doesn't have built-in floating-point arithmetic.

To round to the nearest decimal digit, you add 0.5 and truncate. To round to the nearest tenth, you divide the "nudge factor" by 10, and so forth.

This lack of built-in facilities is what often pushes people to use something like Perl rather than shell:

$ perl -e 'printf "%.2f", 49.765 + 0.005'

Same thing, but all handled by a single process.

Warren Young
  • 72,032
  • 1
    Beware that with the GNU or bash implementations of printf (which convert the numbers to long double), that gives 49.78 for x=49.77 (and 49.77 with zsh / dash's printf for instance which use doubles). With x=49.79, that's revered, zsh's printf gives 49.80 while bash/GNU give 49.79. – Stéphane Chazelas Sep 04 '22 at 12:52
  • All printf that I know of do implement rounding. The round-to-nearest-ties-to-even usually. – QuartzCristal Sep 04 '22 at 13:11
  • Sadly, this appears wrong in a few ways. 1) There is built-in rounding in printf(1), try e.g. sh -c 'printf "%.0f\\n" 2.718' with pretty much any shell. (As far as I read the spec, the %f specifier isn't required, but even things like Dash do support it. I don't see a reason to assume that any shell which implements it, would implement it incorrectly.) – ilkkachu Sep 05 '22 at 18:12
  • 2), that printf "%.2f" $(echo "$x + 0.005" | bc) fails in the general case, with a few values of $x, exactly because of the rounding in printf. E.g. with x=49.772, printf "%.2f" $(echo "$x + 0.005" | bc) prints 49.78, while the correct rounding as per most rules would be 49.77. The logic of adding 0.5 works when the following action is truncation, not rounding. – ilkkachu Sep 05 '22 at 18:12
0

You can use following command for rounding off.

float number = 49.765; printf("%0.2f", number);

You should be able to get the 2 figures after decimal point.

But this will just print, it will not update the value. If you would like to change the value of the variable then you should use below.

#include <math.h>

float val = 49.765;

float rounded_down = floorf(val * 100) / 100;   /* Result: 49.76 */
float nearest = roundf(val * 100) / 100;  /* Result: 49.77 */
float rounded_up = ceilf(val * 100) / 100;      /* Result: 49.77 */

Notice that there are three different rounding rules you might want to choose: round down (ie, truncate after two decimal places), rounded to nearest, and round up. Usually, you want round to nearest.

As several others have pointed out, due to the quirks of floating point representation, these rounded values may not be exactly the "obvious" decimal values, but they will be very very close.

Harshit
  • 109
0

Capture the output of the "ring of commands" in a variable and use printf.

$ x=49.765

$ printf '%.2f\n' "$x" 49.76

The rounding is done over the binary representation of the number with the rule of round-to-nearest-ties-to-even. Please understand that the binary representation is not exactly equal to the given number in most cases.

  • I upvoted as what is stated in this answer is correct, more correct than the most-voted answer anyway, but note that the OP wanted to get 49.77, possibly wanting to round ties up. – Stéphane Chazelas Sep 04 '22 at 12:54
  • Thanks @StéphaneChazelas Yes, he wants 49.77, but he also wants to use printf. I do not know of a shell printf that doesn't use nearest-ties-to-even (the default used in IEEE 754). And even using nearest-ties-up, the binary representation (in ksh and bash) is 49.764999999999999999444888487687 which is slightly below 49.765 and rounds (the same) to 49.76. But, of course, he could use dash and get the 49.77 he is asking for with the exact same code (a 53 bit mantissa in dash while it is 64 bit in bash). – QuartzCristal Sep 04 '22 at 13:07
  • In this system, both dash and zsh (using zsh -c 'printf "%.30f\n%.2f\n" 49.765 49.765' print 49.765000000000000568434188608080 and 49.77. You can try this: https://baseconvert.com/ieee-754-floating-point site where I got this image: https://imgur.com/a/H0PWUBm which clearly shows a number a bit bigger than 49.765 for the double. Maybe your double floats are not equal to my double floats. Are you using an x86 cpu ? @StéphaneChazelas – QuartzCristal Sep 04 '22 at 13:44