dec.h (2593B)
1 /* dec.h - numeros decimales de punto flotante en base 10 (como una calculadora): 2 * mantisa de 18 digitos (15 que se muestran + 3 de guarda) y exponente. 3 * Sin float, sin malloc, sin stdio: corre igual en Linux y en el RP2040. */ 4 #ifndef DEC_H 5 #define DEC_H 6 #include <stdint.h> 7 #include <stdbool.h> 8 9 #define DEC_DIGITS 18 10 #define DEC_EMAX 99 /* |x| < 10^100, como la Casio */ 11 12 enum { DE_OK, DE_MATH }; /* err: fuera de rango, division por cero, dominio */ 13 14 /* valor = m * 10^(e-17), con 10^17 <= m < 10^18 (m = 0 para el cero); 15 * e es el exponente del primer digito (notacion cientifica). */ 16 typedef struct { uint64_t m; int16_t e; uint8_t neg, err; } Dec; 17 18 extern const Dec DEC_ZERO, DEC_ONE; 19 20 Dec dec_int(int64_t v); 21 Dec dec_err(void); 22 /* Lee "123.45", "-1.5E-7", ".5", "2e3"; *end queda en el primer caracter no usado 23 * (NULL si no hay numero). */ 24 Dec dec_parse(const char *s, const char **end); 25 26 Dec dec_add(Dec a, Dec b); 27 Dec dec_sub(Dec a, Dec b); 28 Dec dec_mul(Dec a, Dec b); 29 Dec dec_div(Dec a, Dec b); 30 Dec dec_neg(Dec a); 31 Dec dec_abs(Dec a); 32 Dec dec_sqrt(Dec a); 33 Dec dec_mul_int(Dec a, int64_t k); 34 Dec dec_div_int(Dec a, int64_t k); 35 Dec dec_pow_int(Dec a, int64_t n); /* exacta mientras entre en 18 digitos */ 36 Dec dec_scale10(Dec a, int k); /* a * 10^k */ 37 38 int dec_cmp(Dec a, Dec b); /* -1, 0, 1 */ 39 int dec_cmp_abs(Dec a, Dec b); 40 static inline bool dec_is_zero(Dec a) { return a.m == 0 && !a.err; } 41 static inline bool dec_bad(Dec a) { return a.err != DE_OK; } 42 bool dec_is_int(Dec a); 43 bool dec_to_int(Dec a, int64_t *out); /* falso si no es entero o no entra */ 44 45 Dec dec_trunc(Dec a); /* hacia cero */ 46 Dec dec_floor(Dec a); 47 Dec dec_round_int(Dec a); /* al entero mas cercano (mitad: lejos de cero) */ 48 Dec dec_fmod(Dec a, Dec b); /* a - trunc(a/b)*b, exacto si a y b son "decimales cortos" */ 49 Dec dec_round_sig(Dec a, int n); /* a n digitos significativos, mitad lejos de cero */ 50 Dec dec_round_dec(Dec a, int n); /* a n decimales (Fix), mitad lejos de cero */ 51 /* Pega a cero o a +-1 lo que esta a menos de 'tol' digitos (resultados de trig). */ 52 Dec dec_snap(Dec a, int tol); 53 54 /* Digitos de la mantisa (18, '0'..'9', sin terminar en 0 si se pide) y exponente. */ 55 void dec_digits(Dec a, char d[DEC_DIGITS + 1]); 56 57 /* int64 a texto (str_int usa long, que en la Pico es de 32 bits) */ 58 int i64_text(char *buf, int n, int pos, int64_t v); 59 60 /* Texto simple para depuracion y para guardar: "-1.2345E-7" (round-trip exacto). */ 61 int dec_to_text(Dec a, char *buf, int n); 62 63 #endif