-1

can anybody help with my problem?

Problem: what is the most easiest way to calculate how many numbers are before the decimal and after?

I understand that if, for example, I count 9.456, I can calculate how many numbers there are before the comma by dividing by 10, but it remains 0.456 and how then should I find out the length of the number after the comma? In C.

Thanks for helping

  • 3
    Computer may very well interpret your example as `9.4559999999999965362431`, you need to read ["What Every Programmer Should Know About Floating-Point Arithmetic"](https://floating-point-gui.de/) ... or, vey (**very**) much simpler, treat input as a string! – pmg Nov 01 '20 at 15:41
  • This might help you. https://stackoverflow.com/q/17837654/9992790 – Student18 Nov 01 '20 at 15:50
  • Consider also that it is a matter of context even whether 9.456 is different from 9.4560. Generally speaking, your options for how many fractional digits there are in a number are usually some combination of (1) however many you say there are, and (2) however many were presented in (text) input. – John Bollinger Nov 01 '20 at 15:51
  • If you are talking about a decimal number, that will be in a string format, as floating point variables are not stored as decimal, or with a certain number of decimal places. If the input is coming from `stdin` then read it directly into a string, find the decimal point (if any) and count the digits each side (but not leading or trailing zeros). – Weather Vane Nov 01 '20 at 16:07
  • 1
    There's too many possible interpretations of this problem. Other comments are trying to help, but let's start with this one. Do you have a string or a double? – Joshua Nov 01 '20 at 16:13
  • "Length of number" only makes sense if you are treating the number as a string. So treat it as a string and use `strchr`, `strrchr`, `index`, and/or `rindex` – William Pursell Nov 01 '20 at 16:29
  • @Joshua string. Because it is more convenient or should I replace with double? – Max_insane Nov 01 '20 at 20:04
  • @Max_insane: No. If it comes as string, it is string. – Joshua Nov 01 '20 at 20:07

2 Answers2

1

How to calculate the length of number before decimal and after (?)

Careful what you wish for ....

9.456 is not exactly presentable as a double. It is not of the form some_integer*2some_power.

double a = 9.456;

Instead a nearby representative value is used1. Its exact decimal value is perhaps not that useful for this task:

9.455999999999999516830939683131873607635498046875
//123456789012345678901234567890123456789012345678

In this case the integer digit count is 1 and the fraction count 48.


Instead, a more practical question/answer is: "How to calculate the length of number before decimal point and after of a rounded output?"

This is easier. Print the double using "% .*e" to a string to do the heavy lifting, then parse the output.

The precision selected affects the output: see 99.999 below.

Since we are using the rounded decimal output, avoid trying to code this without using sprintf(). Otherwise the corner cases are many.

Sample:

#include <math.h>
#include <stdio.h>
//                   -   d   .   xxxxxxxxxxx    e   - eeee \0  spare
#define FMT_N(prec) (1 + 1 + 1 + ((prec) - 1) + 1 + 1 + 4 + 1 + 5)
#define FMT_E(prec) (1 + 1 + 1 + ((prec) - 1) + 1)
#define FMT_Z(prec) (1 + 1 + 1 + ((prec) - 1) - 1)

void get_int_fraction_count(double a, int precision, int *integer, int *fraction) {
  *integer = *fraction = 0;
  if (!isfinite(a) || a == 0.0) {
    return;
  }
  char buf[FMT_N(precision)];
  snprintf(buf, sizeof buf, "% .*e", precision - 1, a);
  int expo = atoi(&buf[FMT_E(precision)]);
  int digit_count = precision;
  for (char *z = &buf[FMT_Z(precision)]; *z == '0'; z--) {
    digit_count--;
  }
  // printf("expo:%d digit_count:%d\n", expo, digit_count);
  if (expo >= 0) {
    *integer = expo + 1;
    if (digit_count > *integer) {
      *fraction = digit_count - *integer;
    }
  } else {
    *fraction = digit_count - expo - 1;
  }
}

Test: Recommend to use DBL_DIG digits.

void get_int_fraction_count_test(double a, int precision) {
  int integer;
  int fraction;
  get_int_fraction_count(a, precision, &integer, &fraction);
  printf("a:% .*e i:%d f:%d\n", precision - 1, a, integer, fraction);
}

int main(void) {
  double a = 9.456;
  get_int_fraction_count_test(a, 4);
  get_int_fraction_count_test(a, DBL_DIG);
  get_int_fraction_count_test(0.123, 4);
  get_int_fraction_count_test(0.0123, 4);
  get_int_fraction_count_test(DBL_MAX, 4);
  get_int_fraction_count_test(DBL_TRUE_MIN, 4);
  get_int_fraction_count_test(99.999, 4);
  get_int_fraction_count_test(99.999, 5);
}

Output

a: 9.456e+00 i:1 f:3
a: 9.45600000000000e+00 i:1 f:3
a: 1.230e-01 i:0 f:3
a: 1.230e-02 i:0 f:4
a: 1.798e+308 i:309 f:0
a: 4.941e-324 i:0 f:327
a: 1.000e+02 i:3 f:0
a: 9.9999e+01 i:2 f:3

1 5,323,254,759,551,926 * 2-49

chux - Reinstate Monica
  • 127,356
  • 13
  • 118
  • 231
-1

So we're going to use strchr today.

void getdigitcount(const char number[], size_t *before, size_t *after)
{
    size_t len = strlen(number);
    char *decimal = strchr(number, '.');
    if (!decimal) {
        *before = len;
        *after = 0;
        return;
    }
    while (number[len - 1] == '0')
        len--; /* get rid of trailing zeroes -- if that's wrong get rid of this loop */
    *before = decimal - number;
    *after = len - (decimal - number);
 }

The key is strchr finds the decimal point. From there count before is a subtract and count after is another subtract. But we gotta handle decimal point not found.

Thing about C is it is expected the programmer can use the whole language. This task is annoying without pointers.

Joshua
  • 38,744
  • 8
  • 68
  • 123