1

I'm coding a simple program for class. I've completed it, don't worry, I'm not asking for anyone to do my homework. Let me explain what I want with an example.

My program asks for an amount of bits and converts it to mb, kb and bytes. So, the output if I input 1 bit is:

1 in megabytes is: 0.000000119209290
1 in kilobytes is: 0.000122070312500
1 in bytes is: 0.125000000000000
1 in bits is: 1

So, my question is just an aesthetic one: how could I not show the decimal places that are unnecessary? For example, in the bytes, I would like to only print 0.125, instead of 15 decimals, which isn't that pretty at all.

The source code is:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(void)
{

        unsigned long long int bits;

        printf("Input a quantity of bits: \n");
        scanf("%lld", &bits);

    /*
     * 1 byte = 8 bits.
     * 1 kilobyte = 1024 bytes.
     * 1 megabyte = 1024 kilobytes.
     */
        long double by = ((double) bits) / ((double) 8);
        long double kb = ((double) by)  / ((double) 1024);
        long double mb = ((double) kb) / ((double) 1024);

        printf("%lld in megabytes is: %.15Lf\n", bits, mb);
        printf("%lld in kilobytes is: %.15Lf\n", bits, kb);
        printf("%lld in bytes is: %.15Lf\n", bits, by);
        printf("%lld in bits is: %lld\n", bits, bits);

    return(0);
}

PS: I know I specified 15 decimal places in the printf, I wast just trying which was the best way for me to output the values.

Thank you in advance!

George Rosario
  • 761
  • 11
  • 24
Ignasi Sánchez
  • 75
  • 1
  • 2
  • 10

3 Answers3

4

Use g specifier, like this:

printf("%lld in megabytes is: %.15Lg\n", bits, mb);
printf("%lld in kilobytes is: %.15Lg\n", bits, kb);
printf("%lld in bytes is: %.15Lg\n", bits, by);
printf("%lld in bits is: %lld\n", bits, bits);

However, this will use scientific notation if needed. You could add an if statement like this:

if(fmod(mb, 10) == mb // last digit is not zero
    && mb < 0.000001) // if mb is a small number (the left value may need tuning)
   printf("%lld in megabytes is: %.15Lf\n", bits, mb);
else
   printf("%lld in megabytes is: %.15Lg\n", bits, mb);

A relevant answer is this. Also notice, that I had to use fmod() (under math.h), because mb is not an integer.

Community
  • 1
  • 1
gsamaras
  • 71,951
  • 46
  • 188
  • 305
1

You could make a function to calculate the required number of decimal places. To do it, take the fractional part, and multiply it by 10 until it becomes an integer.

int required_decimal_places(double x)
{
    int counter = 0;

    x -= floor(x);
    while (x != floor(x))
    {
        x *= 10;
        ++counter;
    }

    return counter;
}

Then, output your number with the required number of decimal places:

printf("%lld in megabytes is: %.*f\n", bits, required_decimal_places(mb), mb);

The asterisk (*) in the format string tells the system that the length of output is specified as a parameter.

Note: I replaced long double in your code by double because I am not sure whether it is correct to call the library function floor on long double. I also changed Lf to f inside the format string. The extra accuracy of long double (if any) is not required in the calculations you are doing here.

anatolyg
  • 26,506
  • 9
  • 60
  • 134
0

A possible way might be to print into a string, then to check that the string is accurate enough:

double x= some_number();
char buf[48];
snprintf (buf, sizeof(buf), "%.3f", x);
if (atof(buf) == x) puts(buf);
else {
  snprintf (buf, sizeof(buf), "%.6f", x);
  if (atof(buf) == x) puts(buf);
  else printf("%.15g", x);
}

Read floating point guide; consider comparing with some epsilon e.g perhaps something like if (abs(x-atof(buf)) < 1.0e-5*abs(x))

BTW, be aware of bignum-s and consider GMPlib if you need a lot (more than 8) decimals.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547