Greetings, I'm trying to get some concrete decimals saved for comparisons later. Would it be possible to have a decimal with, for example, 8 decimals?
Thank you!
Greetings, I'm trying to get some concrete decimals saved for comparisons later. Would it be possible to have a decimal with, for example, 8 decimals?
Thank you!
You can not take a specific number of decimals but you can save it in a normal way and then at the time of showing it you can show it with the decimals that you want regardless of what you have just put on the printf% numdecimales.fy ready when comparing them there is no problem given that if one number has three decimal places and the other four, the numbers that follow are all 0, that is, if you have a = 2.3 and b = 3.123 when it is time to show them if you do not put what you have I said before, would be a = 2.3000000000 and b = 3.12300000000 so to compare them there is no problem, the only thing where there may be "problem" is to show it, that if, the variables where you target the numbers has to be float
Greetings
Would it be possible to have a decimal with, for example, 8 decimals?
It would not be possible with the built-in types of the C language, you need a type of fixed coma , and C offers whole types ( short
, int
, long
, ...) and floating point ( float
, double
, long double
).
But even though C does not offer fixed-point types, you can develop fixed-point arithmetic with the existing tools in the language, if so, any operation would require:
A possible approximation would use bit shift operators ( <<
and >>
) since they are equivalent to multiplying by powers of 2 ( <<
) or dividing by powers of 2 ( >>
).
In your case you want 8 decimals, a value of 8 decimal digits (8 10 ) can contain numbers from 0 to 99,999,999 (this is 27 bits 1 ) so we would have 4 bits left for the whole part:
+--------+-----------------------------+
| entero | decimal |
+--------v-----------------------------+
| 0000.0000000000000000000000000000 |
+--------^-----------------------------+
What allows us to have numbers from 0 to 16 (2 4 ) with 8 decimal places.
So, to add 1 and 1 in a fixed point we would do the following:
int valor = (1 << 27) + (1 << 27); // 1 + 1 = 2
The addition and subtraction operations will require moving the bits (multiply) to place the whole part in the right place, but the multiplication and division operations can be done directly:
int valor = (1 << 27) + (1 << 27); // 1 + 1 = 2
valor /= 3; // 2 / 3 = 0.66666666
Let's check it out:
int valor = (1 << 27) + (1 << 27);
printf("%d.%d\n", valor >> 27, valor & ((1 << 27) - 1));
valor /= 3;
printf("%d.%d\n", valor >> 27, valor & ((1 << 27) - 1));
This should show us 2.0
and 0.66666666
but it shows:
2.0 0.89478485
This is because the decimal part is a percentage of an entire unit, so we should normalize it:
int valor = (1 << 27) + (1 << 27);
printf("%d.%f\n", valor >> 27, (valor & ((1 << 27) - 1)) / (double)(1 << 27));
valor /= 3;
printf("%d.%f\n", valor >> 27, (valor & ((1 << 27) - 1)) / (double)(1 << 27));
This produces a correct but badly formatted output:
2.0.000000 0.0.666667
So, to make things easier and work more comfortably, let's use some macros and an auxiliary function:
#define SHIFT 27
#define FRACTION_MASK ((1 << SHIFT) - 1)
void print_punto_fijo(int valor)
{
double e = valor >> SHIFT;
double d = (valor & FRACTION_MASK);
double n = e + (d / (double)(1 << SHIFT));
printf("%.8f\n", n);
}
int main(void)
{
int valor = (1 << SHIFT) + (1 << SHIFT);
print_punto_fijo(valor);
print_punto_fijo(valor / 3);
return 0;
}
2.00000000 0.66666666
But unless you want to develop the fixed-point arithmetic on your own, I advise you to use an existing fixed-point library:
1 99.999.999 10 = 101.111.101.011.110.000.011.111.111 2
Let's see ...
There are two groups of "native" types, which represent integers ( int
, long
and associated) and those that represent numbers in floating point.
The problem with integers is that they do not represent fractional numbers; The problem with floating point numbers is that they do not represent exactly decimal numbers in decimal format. For example, 0.5 has a finite binary expression that fits on any float, but 0.1 needs an infinite number of bits to be represented in binary 1 . See this question for more details , or look for information about the IEEE754 format
The solution?
Use floating point and accept that there may be variations. If you are going to do a calculation with numbers of 8 decimals and in the end the result you round it to 2 decimals, for many applications it will not matter.
Use an integer and "convert the numbers" to operate with integer. For example, if you work with prices, make the variable precio
work with cents (so, for a product of € 9.99, the value of precio
would be 999
). Of course, you have to remember to do the conversion to the correct scale when you show the results. Naturally, you have to choose the type well to serve the range of values (you can not use int
if you work with 20 decimal places and the whole part has 10 figures).
Create your own type. A very crude example would be a struct
with an integer for each decimal position. The problem is that a) is slower than the native types and b) it's more work since you have to create the operators.
In any case there may be free libraries there that implement types with arbitrary decimals.
In general, if accuracy is important, I would opt for the second option.
1 And, as a rule, computers do not have an infinite number of bits.