2

I need to write a program in C that does the following:

Write a program so that when the user enters a floating point number, it rounds off the number to 3 decimal places. When displaying the result, display 5 decimal places, and this means the 4th and 5th decimal place number will both be 0.

How do I round it to 3 decimal places and then display two zeroes? I am not allowed to use any sort of math library functions.

dsta
  • 253
  • 1
  • 6
  • 15

3 Answers3

2
printf("%.5f\n",(int)(number*1000+0.5)/1000.0);
Vaughn Cato
  • 63,448
  • 5
  • 82
  • 132
  • This won't actually do it; there are corner cases where the wrong thing will be printed. – R.. GitHub STOP HELPING ICE Jan 31 '13 at 06:10
  • @R..: Are you talking about cases where the number overflows an integer? – Vaughn Cato Jan 31 '13 at 06:12
  • That's only one case. You also have the fact that multiplication by 1000 is a lossy operation, because 1000 is not a power of two. Maybe other issues too. – R.. GitHub STOP HELPING ICE Jan 31 '13 at 06:14
  • 1
    Basically, what it comes down to is that there's no easy way to round a floating point value to "N decimal places" with floating point math, because floating point numbers are not decimal but binary. pst's answer is the right one because the `printf` family is the **only** tool you have in the standard library that can perform decimal rounding of floating point numbers, and doing decimal rounding of floating point numbers is hard enough that you don't want to attempt it yourself. – R.. GitHub STOP HELPING ICE Jan 31 '13 at 06:18
  • @R..: I see your point, but can you provide a particular example where it doesn't work (other than the obvious one with the integer overflow)? – Vaughn Cato Jan 31 '13 at 06:24
  • 1
    Try `0x1.e84801f9db22dp+20`, which is the closest double to 2000000.1235000001 but is numerically slightly less than 2000000.1235. It should round to 2000000.123, but your algorithm rounds it to 2000000.124. These are just some random test cases I started out playing with; I'm sure you can find plenty more. – R.. GitHub STOP HELPING ICE Jan 31 '13 at 06:37
  • @R..: I tried your example, but I get 2000000.12300. Perhaps because it is using higher precision for internal calculations. – Vaughn Cato Jan 31 '13 at 06:50
  • Are you using (32-bit) x86? If so, there's probably extra intermediate precision. You can avoid this by compiling with `-std=c99` (on a sufficiently new gcc; 4.6 or later is definitely fine) and rewriting the expression as: `(int)(double)((double)(number*1000)+0.5)/1000.0`. Or you could use `-msse2 -mfpmath=sse` so that there's no excess precision. – R.. GitHub STOP HELPING ICE Jan 31 '13 at 06:54
  • @R..: Yes it is 32-bit x86. Rewriting the expression seems to be beyond the scope of the answer, but the point that my code would give incorrect results on some (still standard-conforming) architectures or compilers is valid. – Vaughn Cato Jan 31 '13 at 06:59
  • I suspect your formula works for all double-precision inputs that don't overflow the integer cast if you perform the intermediate operations in an extended-precision type (e.g. ld80), but I have not verified this. If that's true, it could be made to work (via explicit conversions to `long double`) on any system with extended precision; this would not, however, work on systems like ARM where `long double` is identical to `double`. My "rewriting the expression" may seem unfair, but it makes the behavior identical across all IEEE conforming implementations. – R.. GitHub STOP HELPING ICE Jan 31 '13 at 07:19
2

Well, "no math" method :D

printf("%.3f00\n", n);

(Usually subject to Round-to-Nearest-Even; see R..'s comment.)

Community
  • 1
  • 1
  • 1
    The rounding is not implementation-specific, at least not in implementations that support IEEE arithmetic. It matches the current rounding mode, which is, by default, round-to-nearest(even). – R.. GitHub STOP HELPING ICE Jan 31 '13 at 06:13
0

There are two steps to your task:

1) Round the number to three (3) decimal places.

double n = 0.123456;
n = ((int) (n * 1000.0)) / 1000.0; // => 0.123

2) Display the number to five (5) decimal places.

printf("%.5f\n", n); // => 0.12300
maerics
  • 151,642
  • 46
  • 269
  • 291