Sono riuscito a creare un procedimento per convertire un numero decimale in frazione, basato sulla nota regola pratica descritta sui libri di matematica ma è poco adatto come routine di un programma per computer: si ottiene una procedura piuttosto complicata, lenta e poco elegante, anche se devo dire che funziona abbastanza bene. Infatti per utilizzare la regola suddetta devo prima separare la parte intera e quella decimale del numero di partenza, trasformare la parte decimale in un vettore di byte che rappresentano le singole cifre, quindi individuare, se c’è, un gruppo di cifre che si ripete (cosa che richiede la scansione del vettore per diverse volte), quindi contare le cifre dell’antiperiodo, la lunghezza del periodo e da queste informazioni costruire il numeratore e il denominatore della frazione. Se esistesse un algoritmo più semplice per ottenere lo stesso risultato mi piacerebbe conoscerlo. Grazie

Che io sappia non ne esistono altri, ma tale argomento fa parte di rami
delle scienze matematiche, che esulano dalle mie competenze.
Per quello che mi riguarda potrei dare un giudizio sull’implementazione
fatta di questo algoritmo e in particolare sul processo di individuazione
del periodo e antiperiodo, ma non essendo stata fornita nessuna implementazione,
propongo la mia scritta in C, che ritengo abbastanza efficiente.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <math.h>

bool DeterminaPeriodo(char *decimale,char *outPeriodo,char *outAntiPeriodo)
{
int InizioPeriodo;
int LunghezzaPeriodo;
int LunghezzaMassima=strlen(decimale);
char *Periodo=strdup(decimale);

// Ciclo per l'individuazione dell'inizio del periodo
bool PeriodoTrovato=false;
for(InizioPeriodo=0;InizioPeriodo<LunghezzaMassima && !PeriodoTrovato;InizioPeriodo++) {
// Individuazione del periodo
LunghezzaPeriodo=1;
Periodo[0]=decimale[InizioPeriodo];
Periodo[1]=0;

// Ciclo per la lunghezza
while(LunghezzaPeriodo<=LunghezzaMassima-InizioPeriodo-LunghezzaPeriodo) {
// Ciclo per verificare l'esistenza di un periodo
int max=LunghezzaMassima-LunghezzaPeriodo;
int pos=InizioPeriodo+LunghezzaPeriodo;
while(pos<=max && strncmp(Periodo,decimale+pos,LunghezzaPeriodo)==0)
pos+=LunghezzaPeriodo;

if(pos==LunghezzaMassima && LunghezzaPeriodo<LunghezzaMassima) {
PeriodoTrovato=true;
break;
}
else {
Periodo[LunghezzaPeriodo]=decimale[InizioPeriodo+LunghezzaPeriodo];
Periodo[++LunghezzaPeriodo]=0;
}
}
}

if(PeriodoTrovato) {
strcpy(outPeriodo,Periodo);
strncpy(outAntiPeriodo,decimale,InizioPeriodo-1);
outAntiPeriodo[InizioPeriodo-1]=0;
}

free(Periodo);
return PeriodoTrovato;
}

///////////////////////////////////////////////////////////////////////////////
// MAIN

int main(int argc, char *argv[])
{
if(argc!=2)
printf("USO: %s <Numero> ",argv[0]);
else {
char *buffer=argv[1];
printf("Numero = %s ",buffer);

///////////////////////////////////////////////////////////////////////
// Separazione parte decimale e intera

char *punto=strchr(buffer,'.');
if(punto) {
*punto=0;
char *ParteDecimale = punto+1;
char *Periodo = strdup(ParteDecimale);
char *AntiPeriodo = strdup(ParteDecimale);
Periodo[0]=AntiPeriodo[0]=0;

///////////////////////////////////////////////////////////////////
// Determinazione del periodo e antiperiodo

if(DeterminaPeriodo(ParteDecimale,Periodo,AntiPeriodo)==false) {
strcpy(Periodo,"0");
strcpy(AntiPeriodo,ParteDecimale);
}

int m=strlen(Periodo);
int n=strlen(AntiPeriodo);
printf("Periodo = %s "
"Antiperiodo = %s ",
Periodo, AntiPeriodo);

free(Periodo);
free(AntiPeriodo);

///////////////////////////////////////////////////////////////////
// Calcolo della frazione

*punto='.';
double Valore = atof(buffer);
double Denominatore = pow(10,n+m)-pow(10,n);
double Numeratore = Valore*Denominatore;
printf("Frazione = %0.0f/%0.0f ",Numeratore,Denominatore);
}
else
printf("Frazione = %s/1 ",buffer);
}

return 0;
}

Il programma accetta un parametro da riga di comando che sarà un numero
espresso gia sottoforma di vettore di caratteri.
L’individuazione di un periodo è un’elaborazione di una stringa, che alla
fine non risulta neanche troppo pesante dal punto di vista computazionale,
richiedendo delle semplici comparazioni tra sottostringhe di quella data.

I commenti nel codice dovrebbero essere sufficienti, per cui mi dilungo
in noiose spiegazioni.
Invece potrebbero essere più interessanti i seguenti siti.

 

Link:

Matematica
Discreta

Una
spiegazione semplificata

Risorse
matematiche