4

I want to write a code where output will be as precise as the input. Consider if I executed

scanf("%f", &n);
printf("%f", n);

And if I give 1.2 as an input, it should output 1.2 but it outputs 1.200000. It should be same with integers too, if I give 9 as input, it should only output 9, not 9.00. Is there any way I can do this?

Vikas Sangle
  • 632
  • 5
  • 19

4 Answers4

1

OP does not specify how to handle an input like "9.00". I assume OP would like to see "9.00" printed and not "9" as the input gave a tenths and hundredths place.

One needs to read the number first as a string so it can be later assessed for precision. The number and its precision need separate variables. A structure would be recommended as in @bgamlath.

Parse the string with sscanf() or atof().
Parse the string for the location of '.'.

int VikasRead(float *value, int *precision) {
  char buf[100];
  *precision = 0;
  if (fgets(buf, sizeof buf, stdin) == NULL) return EOF;
  int end;
  int retval = sscanf(buf, "%f%n", value, &end);
  char * dp = strchr(buf, '.');
  if (dp != NULL && retval == 1) {
    *precision = &buf[end] - dp;
  }
  return retval;
}

int VikasWrite(float value, int precision) {
  int retval;
  if (precision > 1) {
    // Note: printf("%.*f\n", 0, value) is UB.
    retval = printf("%.*f\n", precision - 1, value);  // 1.234
  }
  else if (precision == 0) {;
    retval = printf("%.0f\n", value);  // 123
    }
  else {
    retval = printf("%#.0f\n", value); // 123.
  }
  return retval;
}

void VikasTest(void) {
  float value;
  int precision;
  while (VikasRead(&value, &precision) == 1) {
    VikasWrite(value, precision);
  }
}

Exponential inputs like 1.23e56 complicates the process but the approach is still the same. Need to additionally look for an 'e' or 'E'.

Some locales use a ',' as a decimal point further complicating matters.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

Try using width specifiers:

printf("%.1f", n);

Read this for more details.

However, a point to note: For float and double: Due to precision limitations, you may not get 1.2 printed as 1.2000 or even 1.2, it may become 1.1996... something like that.

Well, that is completely different topic, and is well discussed on SO, you can try searching for the same on internet or here on SO.

UPDATE:
For variable precision, you can use printf("%*f", <width>, <float number>);. More Details here.

0xF1
  • 6,046
  • 2
  • 27
  • 50
0

One solution is to store all user inputs as they are. Using char pointers and gets() or scanf("%s", ...).

If you want to use them in calculations as well, use atof to convert.

Additionaly, you can use a struct to store both the input representation and the numerical value.

stract Number{
 float val;
 char * representaion; // or only precision if you like.
}
Buddhima Gamlath
  • 2,318
  • 1
  • 16
  • 26
0

Use the format specifier %0.7g as the maximum precision of float is 7 digits

#include <stdio.h>

int numberLenght(float d);

int main(void)
{
    float d;
    printf("input: ");
    scanf("%f", &d);
    printf("your input was: %0.7g\n", d);
    return 0;
}

For double use %0.16g (maximum precision of double is 16 digits)

rullof
  • 7,124
  • 6
  • 27
  • 36
  • Where does "maximum precision of float is 7 digits" and "maximum precision of double is 16 digits" derive? Surely not the C spec. The C spec §5.2.4.2.2 has minimal precision for a `float` and `double` of 6 and 10 digits, but there are not specified limits to the maximum precision. Consider [Printf width specifier to maintain precision of floating-point value](http://stackoverflow.com/questions/16839658/printf-width-specificer-to-maintain-precision-of-floating-point-value/19897395#19897395) – chux - Reinstate Monica Jan 06 '14 at 17:46