Ciao a tutti ragazzi non sapendo cosa fare ho voluto creare una libreria C per le gestione di numeri interi senza segno(NISS) di grosse dimensioni.
Non avendo un esperienza esagerata nella programmazione non ho più idee di come poterla migliorare.
Se avete voglia e vi intriga tutto ciò vi allego quello che ho già fatto cosi che voi possiate darci un'occhiata, e suggerirmi algoritmi migliori (i miei sono un po lenti) o qualsiasi miglioramento voi riteniate corretto. Ve ne sarei molto grato.
Ogni funzione è spiegata e nel file .c ci sono anche delle piccole analisi in termini di tempo sul mio pc.
Più avanti sicuramente aggiungerò una funzione DIV per la divisione intera magari restituendo anche il resto.
Math.h
#ifndef MATH_H
#define MATH_H
#include <stdlib.h>
#include <stdio.h>
/* NISS: Struttura dati per gestire numeri interi senza segno di grosse dimensioni(potenzialmente infinite).
Nota: Se bisogna fare molte operazioni conviene passare alla massima base rappresentabile: UINT_MAX
per por ripassare in base decimale.
*/
typedef struct NISS_ *NISS;
/* Init: Inizializza una struttura dati NISS che conterrà il valore <numero> considerato in base 10
e trasformato in base <base>.*/
NISS Init(unsigned int numero,unsigned int base);
/* Free: Si occupa di deallocare la struttura NISS */
void Free(NISS a);
/* Print: Si occupa di stampare su f, il numero contenuto in a*/
void Print(FILE *f,NISS a);
/* Atoi: Ritorna un valore long long int che rappresenta in base dieci il numero contenuto in a
se si dovesse verificare overflow ritorna valore -1*/
long long int Atoi(NISS a);
/* Cfr: Ritorna numero di cifre del numero contenuto in a*/
unsigned int Cfr(NISS a);
/* Base: Ritorna il valore della base di rappresentazione del numero a*/
unsigned int Base(NISS a);
/* CMP: Funzione che confronta due srutture NISS a e b.
Ritorna 0 se a=b, -1 se a<b, 1 se a>b, 5 in caso di errore.
Nota: l'operazione ha senso solo se a e b sono rappresentati con la stessa base.*/
int CMP(NISS a,NISS b);
/* INC: Funzione che incrementa il valore di a di un unità
Ritorna 1 in caso di fallimento altrimenti 0*/
int INC(NISS a);
/* DEC: Funzione che incrementa il valore di a di un unità
Ritorna 1 in caso di fallimento altrimenti 0*/
int DEC(NISS a);
/* ADD: Funzione che somma due numeri precisamente equivale a: a=a+b.
I numeri a e b devono essere rappresentati con la stessa base.
Ritorna 1 in caso di fallimenro altrimenti 0*/
int ADD(NISS a,NISS b);
/* SUB: Funzione equivalente a: a=a-b. Notare che NISS rappresenta numeri senza segno perciò ha senso solo se a>=b.
I numeri a e b devono essere rappresentati con la stessa base.
Ritorna 1 in caso di fallimento altrimenti 0*/
int SUB(NISS a,NISS b);
/* MUL: Funzione equivalente a: a=a*b. Il prametro a deve essere passato per riferimento.
I numeri a e b devono essere rappresentati con la stessa base.
Ritorna 1 in caso di fallimento altrimenti 0*/
int MUL(NISS *a,NISS b);
/* CHGBase: Funzione che cambia la base di rappresentazione del parametro a.
La base finale è determinata dal valore del paramtro <base>(massimo: UINT_MAX).
Ritorna valore 1 in caso di fallimento altrimenti 0*/
int CHGBase(NISS *a,unsigned int base);
#endif // MATH_H
Math.c
#include "Math.h"
#define CAR 16
char legenda[CAR+1]="0123456789ABCDEF";
/* NISS: Struttura dati per gestire numeri interi senza segno di grosse dimensioni.
- vect: vettore di interi, ogni sua locazione rappresenta una cifra.
- base: indentifica la base di rappresentazione del numero contenuto in vect.(dimensione massima UINT_MAX)
- size: identifica il numero di cifre 'locazioni' di vect.(dimensione massima UINT_MAX)
*/
struct NISS_{
unsigned int *vect;
unsigned int base;
unsigned int size;
};
NISS Init(unsigned int numero,unsigned int base){///100.000.000(cicli con anche Free): 28.8 Secondi numero=rand()*rand(),base=rand()+2
NISS a=NULL;
unsigned int v[sizeof(unsigned int)*8]={0};
int i;
if(base<=1)
return NULL;
a=(NISS)malloc(sizeof(struct NISS_));
if(a==NULL)
return NULL;
if(numero==0){
a->vect=(unsigned int*)malloc(sizeof(unsigned int));
if(a->vect==NULL){
free(a);
return NULL;
}
a->base=base;
a->size=1;
a->vect[0]=0;
return a;
}
for(i=0;i<sizeof(unsigned int)*8;i++){
if(v[i]==0&&numero==0)
break;
v[i]=numero%base;
numero=numero/base;
}
while(i>=0&&v[i]==0)
i--;
a->vect=(unsigned int*)malloc(sizeof(unsigned int)*(i+1));
if(a->vect==NULL){
free(a);
return NULL;
}
a->base=base;
a->size=i+1;
for(i=0;i<a->size;i++)
a->vect[i]=v[a->size-i-1];
return a;
}
void Free(NISS a){
if(a==NULL)
return;
if(a->vect==NULL){
free(a);
return;
}
free(a->vect);
free(a);
a=NULL;
}
void Print(FILE *f,NISS a){
if(f==NULL||a->vect==NULL)
return;
int i;
if(a->base<=16){
for(i=0;i<a->size;i++)
fprintf(f,"%c",legenda[a->vect[i]]);
fprintf(f,"\n");
return;
}
for(i=0;i<a->size;i++)
fprintf(f,"%u ",a->vect[i]);
fprintf(f,"\n");
}
long long int Atoi(NISS a){
long long int temp=0;
int i;
if(a==NULL||a->vect==NULL)
return -1;
for(i=0;i<a->size;i++){
temp=temp*a->base;
if(temp<0)
return -1;
temp=temp+a->vect[i];
if(temp<0)
return -1;
}
return temp;
}
unsigned int Cfr(NISS a){
if(a==NULL)
return -1;
return a->size;
}
unsigned int Base(NISS a){
if(a==NULL)
return -1;
return a->base;
}
int CMP(NISS a,NISS b){
if(a==NULL||a->vect==NULL||b==NULL||b->vect==NULL||a->base!=b->base)
return 5;
int i;
if(a->size>b->size)
return 1;
else if(a->size<b->size)
return -1;
for(i=0;i<a->size;i++)
if(a->vect[i]<b->vect[i])
return -1;
else if(a->vect[i]>b->vect[i])
return 1;
return 0;
}
int INC(NISS a){///1.000.000.000(cicli): 8.21 Secondi a=(0,10)
if(a==NULL||a->vect==NULL)
return EXIT_FAILURE;
int i=a->size-1;
while(i>=0&&a->vect[i]==a->base-1){
a->vect[i]=0;
i--;
}
if(i<0){
a->size++;
a->vect=(unsigned int*)realloc(a->vect,sizeof(unsigned int)*a->size);
if(a->vect==NULL){
free(a);
a=NULL;
return EXIT_FAILURE;
}
for(i=a->size-1;i>0;i--)
a->vect[i]=a->vect[i-1];
a->vect[i]=0;
}
a->vect[i]++;
return EXIT_SUCCESS;
}
int DEC(NISS a){///1.000.000.000(cicli): 8.35 Secondi a=(1.000.000.000,10)
if(a==NULL||a->vect==NULL||(a->size==1&&a->vect[0]==0))
return EXIT_FAILURE;
if(a->size==1&&a->vect[0]==1){
a->vect[0]=0;
return EXIT_SUCCESS;
}
int i=a->size-1;
while(i>=0&&a->vect[i]==0){
a->vect[i]=a->base-1;
i--;
}
///Siccome cosideriamo il dato di input corretto non cè bisogno di controllare i<0 significherrebe
///che il vettore ha come primo elemento uno 0, cosa non possibile.
if(i==0&&a->vect[i]==1){
a->size--;
for(i=0;i<a->size;i++)
a->vect[i]=a->vect[i+1];
a->vect=(unsigned int*)realloc(a->vect,sizeof(unsigned int)*a->size);
return EXIT_SUCCESS;
}
a->vect[i]--;
return EXIT_SUCCESS;
}
int ADD(NISS a,NISS b){///1.000.000.000(cicli): 29.54 Secondi ADD(a,b) a=(0,10) b=(4,10)
if(a==NULL||a->vect==NULL||b==NULL||b->vect==NULL||a->base!=b->base)
return EXIT_FAILURE;
int i,j,carry;
long long int temp;
if(a->size<b->size){
a->vect=(unsigned int*)realloc(a->vect,sizeof(unsigned int)*b->size);
if(a->vect==NULL){
free(a);
a=NULL;
return EXIT_FAILURE;
}
for(i=b->size-1;i>=b->size-a->size;i--)
a->vect[i]=a->vect[i-b->size+a->size];
while(i>=0)
a->vect[i--]=0;
a->size=b->size;
}
for(i=a->size-1,j=b->size-1,carry=0;i>=0&&j>=0;i--,j--){
temp=(long long int)a->vect[i]+b->vect[j]+carry;
if(temp/a->base>0){
carry=1;
a->vect[i]=temp%a->base;
}
else{
carry=0;
a->vect[i]=temp;
}
}
if(carry){
while(i>=0&&a->vect[i]==a->base-1){
a->vect[i]=0;
i--;
}
if(i==-1){
a->size++;
a->vect=(unsigned int*)realloc(a->vect,sizeof(unsigned int)*a->size);
if(a->vect==NULL){
free(a);
a=NULL;
return EXIT_FAILURE;
}
for(i=a->size-1;i>0;i--)
a->vect[i]=a->vect[i-1];
a->vect[i]=0;
}
a->vect[i]++;
}
return EXIT_SUCCESS;
}
int SUB(NISS a,NISS b){///1.000.000.000(cicli): 22.91 Secondi SUB(a,b) a=(UINT_MAX,10),b=(4,10)
if(a==NULL||a->vect==NULL||b==NULL||b->vect==NULL||a->base!=b->base||CMP(a,b)==-1)
return EXIT_FAILURE;
int i,j,carry,temp;
for(i=a->size-1,j=b->size-1,carry=0;i>=0&&j>=0;i--,j--){
temp=a->vect[i]-b->vect[j]+carry;
if(temp<0){
a->vect[i]=a->vect[i]+a->base+carry-b->vect[j];
carry=-1;
}
else{
carry=0;
a->vect[i]=temp;
}
}
if(carry){
while(a->vect[i]==0){
a->vect[i]=a->base-1;
i--;
}
a->vect[i]--;
}
for(i=0;i<a->size&&a->vect[i]==0;i++);
if(i!=0){
if(i==a->size){
a->size=1;
a->vect=(unsigned int*)realloc(a->vect,sizeof(unsigned int));
if(a->vect==NULL){
free(a);
a=NULL;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
for(j=0;j<a->size-i;j++)
a->vect[j]=a->vect[j+i];
a->size=a->size-i;
a->vect=(unsigned int*)realloc(a->vect,sizeof(unsigned int)*a->size);
if(a->vect==NULL){
free(a);
a=NULL;
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}
int MUL(NISS *a,NISS b){/// 100.000(cicli): 76.69 Secondi MUL(&a,b) a=(1,10),b=(2,10)
if((*a)==NULL||(*a)->vect==NULL||b==NULL||b->vect==NULL||(*a)->base!=b->base)
return EXIT_FAILURE;
int i,j,z,x,t,carry;
long long int temp,temp1;
NISS c=NULL;
c=(NISS)malloc(sizeof(struct NISS_));
if(c==NULL)
return EXIT_FAILURE;
c->size=(*a)->size+b->size;
c->base=(*a)->base;
c->vect=(unsigned int*)calloc(c->size,sizeof(unsigned int));
if(c->vect==NULL){
free(c);
return EXIT_FAILURE;
}
//Considero aSize>bSize
for(i=b->size-1,z=c->size-1;i>=0;i--,z--){
for(j=(*a)->size-1,x=z,carry=0;j>=0;j--,x--){
temp=(long long int)(*a)->vect[j]*b->vect[i]+carry;
carry=temp/c->base;
if(carry>0){
temp1=(long long int)c->vect[x]+(long long int)temp%c->base;
if(temp1/c->base>0){
c->vect[x]=temp1%c->base;
t=x-1;
while(c->vect[t]==c->base-1){
c->vect[t]=0;
t--;
}
c->vect[t]++;
}
else
c->vect[x]=temp1;
}
else{
temp1=(long long int)c->vect[x]+(long long int)temp%c->base;
if(temp1/c->base>0){
t=x-1;
c->vect[x]=temp1%c->base;
while(c->vect[t]==c->base-1){
c->vect[t]=0;
t--;
}
c->vect[t]++;
}
else
c->vect[x]=temp1;
}
}
if(carry){
temp1=(long long int)c->vect[x]+carry;
if(temp1/c->base>0){
c->vect[x]=temp1%c->base;
x--;
while(c->vect[x]==c->base-1){
c->vect[x]=0;
x--;
}
c->vect[x]++;
}
else
c->vect[x]=temp1;
}
}
i=0;
while(i<c->size-1&&c->vect[i]==0)
i++;
if(i!=0){
for(j=0;j<c->size-i;j++)
c->vect[j]=c->vect[j+i];
c->size=c->size-i;
}
Free((*a));
(*a)=c;
return EXIT_SUCCESS;
}
int CHGBase(NISS *a,unsigned int base){/// 2^(100.000)in base UINT_MAX -> 2^(100.000) in base 10 Tempo: 26.30 Secondi
if((*a)==NULL||(*a)->vect==NULL)
return EXIT_FAILURE;
NISS temp=NULL,basei=NULL,cifra;
int i;
temp=Init(0,base);
if(temp==NULL)
return EXIT_FAILURE;
basei=Init((*a)->base,base);
if(basei==NULL){
Free(temp);
return EXIT_FAILURE;
}
for(i=0;i<(*a)->size;i++){
if(MUL(&temp,basei)){
Free(temp);
Free(basei);
return EXIT_FAILURE;
}
cifra=Init((*a)->vect[i],base);
if(cifra==NULL){
Free(temp);
Free(basei);
return EXIT_FAILURE;
}
if(ADD(temp,cifra)){
Free(temp);
Free(cifra);
Free(basei);
return EXIT_FAILURE;
}
Free(cifra);
}
Free(basei);
Free((*a));
(*a)=temp;
return EXIT_SUCCESS;
}