start converting numbers to rational numbers

This commit is contained in:
2024-05-08 00:38:02 +01:00
parent c77a4b1361
commit a71071d858
6 changed files with 129 additions and 27 deletions

View File

@@ -1,6 +1,8 @@
{ {
"files.associations": { "files.associations": {
"*.ejs": "html", "*.ejs": "html",
"stdio.h": "c" "stdio.h": "c",
"stdbool.h": "c",
"string.h": "c"
} }
} }

View File

@@ -1,3 +1,3 @@
build: build:
mkdir -p bin mkdir -p bin
gcc -O3 -o bin/cargon $(shell find src -name '*.c') -Wall -Wextra -Werror gcc -O3 -o bin/cargon $(shell find src -name '*.c') -lm -Wall -Wextra -Werror

Binary file not shown.

View File

@@ -1,32 +1,29 @@
#include "string/string.h" #include "string/string.h"
#include "number/number.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
void initialize() {
initNumber();
}
void cleanup() {
cleanupNumber();
}
int main() { int main() {
char* str = malloc(100 * sizeof(char)); initialize();
if (str == NULL) { char *code = "1.2e20";
printf("Failed to allocate memory\n"); struct number mynum = translateNumber(code);
if (mynum.denominator == 0) {
printf("Invalid number\n");
return 1; return 1;
} }
strcpy(str, " \t\n\r\f\vHello, World! \t\n\r\f\v"); double f = 1.0 * mynum.numerator / mynum.denominator;
char* clone = cloneString(str); printf("Numerator: %ld\n", mynum.numerator);
printf("Denominator: %lu\n", mynum.denominator);
if (clone == NULL) { printf("Float: %lf\n", f);
printf("Failed to clone string\n");
return 1;
}
stripString(clone, WHITE_SPACE);
printf("Original string: \"%s\"\n", str);
free(str);
printf("Cloned string: \"%s\"\n", clone);
free(clone);
return 0; return 0;
} }

View File

@@ -1,9 +1,108 @@
#include "number.h" #include "number.h"
#include "../string/string.h"
#include <string.h> #include <string.h>
#include <regex.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
struct number translateNumber(char *code) { regex_t numberCompile;
void initNumber()
{
int compileError;
compileError = regcomp(&numberCompile, "^( *)(-)?(((([0-9]+(\\.[0-9]+)?)|(\\.[0-9]+))(e((\\-|\\+)?([0-9]+)))?))( *)$", REG_EXTENDED);
if (compileError)
{
char errorBuffer[1024];
regerror(compileError, &numberCompile, errorBuffer, sizeof(errorBuffer));
fprintf(stderr, "Error compiling regex: %s\n", errorBuffer);
exit(1);
}
}
void cleanupNumber()
{
regfree(&numberCompile);
}
int gcd(int64_t a, int64_t b)
{
while (b != 0)
{
int temp = b;
b = a % b;
a = temp;
}
return a;
}
void simplifyFraction(int64_t *numerator, int64_t *denominator)
{
int common_divisor = gcd(*numerator, *denominator);
*numerator /= common_divisor;
*denominator /= common_divisor;
}
void doubleToFraction(double num, int64_t *numerator, uint64_t *denominator) {
int currentSign = (num < 0) ? -1 : 1;
num = fabs(num);
double tolerance = 1.0e-10;
double h1 = 1, h2 = 0, k1 = 0, k2 = 1;
double b = num;
do {
double a = floor(b);
double aux = h1;
h1 = a * h1 + h2;
h2 = aux;
aux = k1;
k1 = a * k1 + k2;
k2 = aux;
b = 1 / (b - a);
} while (fabs(num - h1 / k1) > num * tolerance);
*numerator = (int64_t)(h1 * currentSign);
*denominator = (uint64_t)k1;
}
struct number translateNumber(char *code)
{
char *codeClone = cloneString(code);
stripString(codeClone, WHITE_SPACE);
int reti = regexec(&numberCompile, codeClone, 0, NULL, 0);
if (reti == REG_NOMATCH)
{
return (struct number){
.numerator = 0,
.denominator = 0
};
}
struct number num; struct number num;
num.sign = code[0] == '-' ? 1 : 0; num.numerator = 0;
num.denominator = 1;
double coefficient = 0;
int exponent = 0;
char *e = strchr(codeClone, 'e');
if (e) {
*e = '\0';
e++;
if (*e == '+') e++;
exponent = atoi(e);
}
coefficient = atof(codeClone);
doubleToFraction(coefficient, &num.numerator, &num.denominator);
if (exponent > 0) {
num.numerator *= (int64_t)pow(10, exponent);
} else if (exponent < 0) {
num.denominator *= (int64_t)pow(10, -exponent);
}
return num; return num;
} }

View File

@@ -2,13 +2,17 @@
#define CLONESTRING_HNUMBER_H #define CLONESTRING_HNUMBER_H
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
struct number { struct number {
uint8_t sign; int64_t numerator;
uint64_t numerator;
uint64_t denominator; uint64_t denominator;
}; };
struct number translateNumber(char *code); struct number translateNumber(char *code);
void initNumber();
void cleanupNumber();
#endif // NUMBER_H #endif // NUMBER_H