Well, there's the obvious stuff, like whitespace and declaring variables at their first point of use. For example:
static void print_decimal(double decimal, int precision)
{
size_t integer;
while (precision--)
{
decimal *= 100.;
integer = (int)decimal;
could usefully be rewritten as
static void print_decimal(double decimal, int precision)
{
while (precision--) {
decimal *= 100.;
size_t integer = (int)decimal;
This spots a bug: you fail to handle negative inputs. If you want integer
to hold a signed int
, you should define it as int
(not size_t
); and vice versa, if you want it to hold an unsigned size_t
, you should be casting (size_t)decimal
(not (int)decimal
).
if (!precision && (integer % 10) >= 5 && decimal != (double)integer)
integer += 10;
This line could use some comments. I imagine it has something to do with rounding?
printf("%i", integer);
It's more idiomatic to use printf("%d", integer)
to print a decimal integer in C (and C++). True, %i
exists, but it's deservedly obscure.
(Also, because of the above bug where you made integer
a size_t
, down here you should be using %zu
to print it. But once you make it an int
, you can go back to using %d
.)
Every compiler will warn you about the format-string mismatch between %i
and size_t
. Are you compiling with -Wall
? (No.) Why not? (There's no reason not to.) So, start compiling with -Wall
today! It'll find your bugs so that you don't have to.
Performance-wise... I conclude from context that you expect this line to only ever print one digit, is that right? That is, your code could benefit from some "design by contract":
assert(0 <= integer && integer <= 9);
printf("%i", integer);
If the assertion is correct, then we can speed up the code by writing simply
assert(0 <= integer && integer <= 9);
putchar('0' + integer);
However, by adding the assertion, we have made the code a little bit testable. We can write some simple tests — just loop over all the floating-point numbers in the world and see if any of them fail the assertion — and indeed it doesn't take long to find one that fails.
print_decimal(0.097, 2);
This prints
010
when it should actually have printed
10
according to my understanding of your intent.
Which reminds me: print_decimal
is a weird name for this function, since it literally does not have the ability to print a decimal point! Even your example print_decimal(65.226, 4)
actually prints 652260
, not 65.2260
. This seems problematic for your prospective users.
So in conclusion:
- Make your code testable.
- Test your code.
- Compile your code with
-Wall
.