Discussione:
realizzare programma in c che faccia sottrazione tra due numeri naturali da 20 cifre
(troppo vecchio per rispondere)
Andre_Santarell
2006-07-21 09:33:41 UTC
Permalink
[c] realizzare programma che fa sottrazione tra 2 numeri naturali da 20
cifre
ciao a tutti
per l'università devo realizzare un programma in c (non in c++ o
altro)

premesso che le mie conoscenze sono molto limitate, il programma deve
fare la sottrazione tra due numeri naturali di 20 cifre. o meglio da un
numero di massimo 20 cifre ne va sottratto un altro qualsiasi


ho già realizzato un semplice programma di sottrazione tra due
numeri, il problema e' che se inserisco numeri di oltre dieci cifre mi
sballa tutto quanto

come posso fare per risolvere il problema?
potete aiutarmi ?
Giorgio Silvestri
2006-07-21 10:29:36 UTC
Permalink
Post by Andre_Santarell
[c] realizzare programma che fa sottrazione tra 2 numeri naturali da 20
cifre
ciao a tutti
per l'università devo realizzare un programma in c (non in c++ o
altro)
premesso che le mie conoscenze sono molto limitate, il programma deve
fare la sottrazione tra due numeri naturali di 20 cifre. o meglio da un
numero di massimo 20 cifre ne va sottratto un altro qualsiasi
ho già realizzato un semplice programma di sottrazione tra due
numeri, il problema e' che se inserisco numeri di oltre dieci cifre mi
sballa tutto quanto
come posso fare per risolvere il problema?
potete aiutarmi ?
Un metodo semplice, per il caso più generale di
qualunque numero di cifre occorre allocazione
dinamica della memoria, potrebbe essere quello
di rappresentare l'intero con un array di caratteri e poi lavorare
sulla rappresentazione "testuale" del numero stesso.
L'input/output avviene quindi come per le stringhe.

Es:

#define MAX_NUM_LEN 20

typedef struct {
char rappresentazione[MAX_NUM_LEN+1+1]; /* potrebbero servire lo
'\0' e il segno */
} Numero;

Bisogna fare attenzione a rappresentare i negativi e lavorare bene in
complemento
a 2 o 1 o altro.

Le routine devi farle tu altrimenti non vale ...


Giorgio Silvestri
Andre_Santarell
2006-07-21 12:14:32 UTC
Permalink
Post by Giorgio Silvestri
Post by Andre_Santarell
[c] realizzare programma che fa sottrazione tra 2 numeri naturali da 20
cifre
ciao a tutti
per l'università devo realizzare un programma in c (non in c++ o
altro)
premesso che le mie conoscenze sono molto limitate, il programma deve
fare la sottrazione tra due numeri naturali di 20 cifre. o meglio da un
numero di massimo 20 cifre ne va sottratto un altro qualsiasi
ho già realizzato un semplice programma di sottrazione tra due
numeri, il problema e' che se inserisco numeri di oltre dieci cifre mi
sballa tutto quanto
come posso fare per risolvere il problema?
potete aiutarmi ?
Un metodo semplice, per il caso più generale di
qualunque numero di cifre occorre allocazione
dinamica della memoria, potrebbe essere quello
di rappresentare l'intero con un array di caratteri e poi lavorare
sulla rappresentazione "testuale" del numero stesso.
L'input/output avviene quindi come per le stringhe.
#define MAX_NUM_LEN 20
typedef struct {
char rappresentazione[MAX_NUM_LEN+1+1]; /* potrebbero servire lo
'\0' e il segno */
} Numero;
Bisogna fare attenzione a rappresentare i negativi e lavorare bene in
complemento
a 2 o 1 o altro.
Le routine devi farle tu altrimenti non vale ...
Giorgio Silvestri
ciao Giorgio grazie del tuo aiuto
non ho capito bene il discorso del lavorare in complemento..
puoi essere più chiaro a riguardo?
intanto grazie
oggi provo a buttare giù qualcosa e dopo lo posto così poi mi dici..
;)
grazie ancora
ciao
Giorgio Silvestri
2006-07-21 16:33:52 UTC
Permalink
"Andre_Santarell" <***@gmail.com> ha scritto nel messaggio news:***@p79g2000cwp.googlegroups.com...
Giorgio Silvestri ha scritto:

[...]
Post by Andre_Santarell
Post by Giorgio Silvestri
#define MAX_NUM_LEN 20
typedef struct {
char rappresentazione[MAX_NUM_LEN+1+1]; /* potrebbero servire lo
'\0' e il segno */
} Numero;
Bisogna fare attenzione a rappresentare i negativi e lavorare bene in
complemento
a 2 o 1 o altro.
Le routine devi farle tu altrimenti non vale ...
Giorgio Silvestri
ciao Giorgio grazie del tuo aiuto
non ho capito bene il discorso del lavorare in complemento..
puoi essere più chiaro a riguardo?
Forse l'aiuto è fuorviante ma volevo solo dire che se dovessi
fare una scelta per rappresentare i numeri negativi
hai diverse possibilità:


Es: il numero -1 diventa, dentro rappresentazione[]:

1) In modo testo: rappresentazione[] = "-1"
2) Complemento alla base: rappresentazione[] = "99999999999999999999"
3) Complemento alla base-1: rappresentazione[] = "99999999999999999998"
4) altro...

dove con base intendo 10 e non 2 come nel precedente post.

Naturalmente devi fare anche delle opportune routine
di input/output dei numeri.

Dipende come ti trovi meglio e quali operazioni in futuro
dovrai fare su tali rappresentazioni...


Giorgio Silvestri
Giorgio Silvestri
2006-07-21 18:26:11 UTC
Permalink
Post by Giorgio Silvestri
[...]
Post by Andre_Santarell
Post by Giorgio Silvestri
#define MAX_NUM_LEN 20
typedef struct {
char rappresentazione[MAX_NUM_LEN+1+1]; /* potrebbero servire lo
'\0' e il segno */
} Numero;
Bisogna fare attenzione a rappresentare i negativi e lavorare bene in
complemento
a 2 o 1 o altro.
Le routine devi farle tu altrimenti non vale ...
Giorgio Silvestri
ciao Giorgio grazie del tuo aiuto
non ho capito bene il discorso del lavorare in complemento..
puoi essere più chiaro a riguardo?
Forse l'aiuto è fuorviante ma volevo solo dire che se dovessi
fare una scelta per rappresentare i numeri negativi
1) In modo testo: rappresentazione[] = "-1"
2) Complemento alla base: rappresentazione[] = "99999999999999999999"
3) Complemento alla base-1: rappresentazione[] = "99999999999999999998"
4) altro...
dove con base intendo 10 e non 2 come nel precedente post.
Naturalmente devi fare anche delle opportune routine
di input/output dei numeri.
Dipende come ti trovi meglio e quali operazioni in futuro
dovrai fare su tali rappresentazioni...
Giorgio Silvestri
Naturalmente l'idea dell'array di caratteri è appunto solo un'idea.
Un modo più serio ed efficiente è quello di rappresentare i numeri
con un array di int/long o altro e lavorare su di essi a pezzi.
Cioè prima sugli elementi LSB via via fino a quelli MSB
senza mai incorrere in overflow gestendo bene i riporti ecc.

Molti anni fa feci una libreria per gestire appunto numeri
in precisione illimitata, solo la memoria del PC era un limite ...
Gestendo la memoria in modo dinamico e trattando i numeri
appunto come array che evolvono mano a mano che il
numero cresce.
La complicazione sta nel fatto che come dicevo tutte le
operazioni intermedi vanno fatte in modo da non
superare mai il limite imposto dal tipo usato per
rappresentare il singolo digit, int o long che sia.

Spero di non aver complicato troppo. Prendi questo
solo come un'altra idea ...


Giorgio Silvestri
Andre_Santarell
2006-07-23 10:59:57 UTC
Permalink
ciao grazie

dunque ora come ora per fare il tutto sto facendo nel seguente modo:

- Leggo il primo numero da input (come stringa) e verifico che sia
lungo 20 caratteri;
- Leggo il secondo numero da input e verifico che sia lungo 20
caratteri o meno;
- Usando la funzione "atoi" dentro ad un for converto carattere per
carattere la stringa in interi, che metto in un array (lo fo per
entrambi i numeri)
- Con una funzione costruita ad hoc eseguo la sottrazione tra i due
array, facendo attenzione ai riporti e alla lunghezza dei due array;

Il problema arriva in quest'ultimo punto
Infatti non capisco perché:
1) devo porre se la prima cifra è minore della secondaun risultato
uguale a zero

2) mettiamo che ad esempio si voglia fare 123 meno 4

sarebbe necessario che il programma legga i due numeri come 123 meno
004 e non come 123 meno 400
il problema infatti e' far partire ilprogramma a fare la sottrazione
dall'ultima cifra e non dalla prima.. te hai consigli per fare ciò?


viceversa avevamo pensato di fare leggere al programma 123 come
00000000000000000123
meno
00000000000000000003

ossia aggiungendo all'inizio del numero tanti zeri quanti sono le
cifre mancanti per arrivare a 20.
ma come fare questo?


una volta che si hanno i due numeri a 20 cifre complete si pensava di
fargli fare una sottrazione tra prima cifra da sinistra del primo
numero e prima cifra da sinistra del secondo numero. e che quindi
controllasse che:
se la cifra del primo numero e' maggiore o uguale aquella del secondo
faccia la semplice sottrazione tra due numeri e la memorizzi
se invece la cifra del primo numero è minore di quella del secondo
consideri la prima cifra con l'aggiunta di 10, quindi faccia la normale
sottrazione e scali il risultato dell' operazione delle due cifre
precedenti di uno.

ci sono modi più rapidi?
grazie mille
Giorgio Silvestri
2006-07-23 16:06:01 UTC
Permalink
Post by Andre_Santarell
ciao grazie
- Leggo il primo numero da input (come stringa) e verifico che sia
lungo 20 caratteri;
- Leggo il secondo numero da input e verifico che sia lungo 20
caratteri o meno;
- Usando la funzione "atoi" dentro ad un for converto carattere per
carattere la stringa in interi, che metto in un array (lo fo per
entrambi i numeri)
Senza vedere il codice, che sarebbe
interessante investigare quando hai qualcosa pronto, ti posso
dire che le ottimizzazioni su questo genere di cose sono
praticamente infinite. Vediamo qualcosa.

Se il tuo array di interi è lungo come quello dell'input
allora atoi è totalmente inutile, e anche l'array di interi a questo
punto!

Puoi ottenere il valore intero corrispondente del digit
i-esimo e metterlo direttamente nell'array di input
nel modo seguente:

#define MAX_NUM_LEN 20

int i;

for (i=0; i<MAX_NUM_LEN; ++i) {
rappresentazione[i] -= '0';
}

E' chiaro cosa ho fatto ? Ora rappresentazione[i] è
un vero intero da 0 a 9.

Assumiamo input corretto.
Cioè tutte le cifre sono caratteri tra '0' e '9'.
Post by Andre_Santarell
- Con una funzione costruita ad hoc eseguo la sottrazione tra i due
array, facendo attenzione ai riporti e alla lunghezza dei due array;
Il problema arriva in quest'ultimo punto
1) devo porre se la prima cifra è minore della secondaun risultato
uguale a zero
2) mettiamo che ad esempio si voglia fare 123 meno 4
sarebbe necessario che il programma legga i due numeri come 123 meno
004 e non come 123 meno 400
il problema infatti e' far partire ilprogramma a fare la sottrazione
dall'ultima cifra e non dalla prima.. te hai consigli per fare ciò?
viceversa avevamo pensato di fare leggere al programma 123 come
00000000000000000123
meno
00000000000000000003
ossia aggiungendo all'inizio del numero tanti zeri quanti sono le
cifre mancanti per arrivare a 20.
ma come fare questo?
Una volta che in una stringa di lunghezza n, n <= MAX_NUM_LEN
vuoi riempire con dei '0' a sinistra puoi fare così:

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

#define MAX_NUM_LEN 20

typedef struct {
char rappresentazione[MAX_NUM_LEN+1+1];
} Numero;

static void fill_with_0(Numero *x)
{
size_t n;

n = strlen(x->rappresentazione);
if (n < MAX_NUM_LEN) {
/* non memcpy !!! */
if (n) {
memmove(&x->rappresentazione[MAX_NUM_LEN -
n],x->rappresentazione,n);
}
memset(x->rappresentazione,'0',MAX_NUM_LEN - n);
x->rappresentazione[MAX_NUM_LEN] = '\0'; /* solo per stampare */
}
}

int main(void)
{
Numero numero;

sprintf(numero.rappresentazione,"9");
fill_with_0(&numero);
printf("%s\n",numero.rappresentazione);
return EXIT_SUCCESS;
}
Post by Andre_Santarell
una volta che si hanno i due numeri a 20 cifre complete si pensava di
fargli fare una sottrazione tra prima cifra da sinistra del primo
numero e prima cifra da sinistra del secondo numero. e che quindi
se la cifra del primo numero e' maggiore o uguale aquella del secondo
faccia la semplice sottrazione tra due numeri e la memorizzi
se invece la cifra del primo numero è minore di quella del secondo
consideri la prima cifra con l'aggiunta di 10, quindi faccia la normale
sottrazione e scali il risultato dell' operazione delle due cifre
precedenti di uno.
ci sono modi più rapidi?
Questo metodo è estremamante inefficiente.
Bisogna partire da LSB come ho detto in precedenza.
Ricalcando come si fa con carta e penna.
Considera quello che dovresti fare con la seguente
coppia di numeri:

10000000000000000000
meno
00000000000000000001

e partendo da sinistra!

Mentre partendo da LSB (destra) non devi avere memoria di più di
un riporto!
A dire la verità si potrebbe migliorare anche la versione da
sinistra. Comunque da destra è più facile, perlomeno più
consueto...


Se invece vuoi usare un ulteriore array di interi, in modo efficiente,
allora tale array ha dimensione molto minore
di MAX_NUM_LEN.
Nel nostro caso basterebbe grande 3 se usiamo i long.
In questo modo tutti i conti interni sono ancora più efficienti.

Questo problema nasce con dimensioni gigantesche dei numeri
stessi, quando l'I/O è limitato rispetto la mole di calcolo effettivo.

Nello specifico l'intero calcolo della differenza tra due
numeri diventerebbe:

#define LSIZE 3

long out_array[LSIZE];
long num1[LSIZE];
long num2[LSIZE];

/* ... */
out_array[2] = num1[2] - num2[2]; /* + gestione riporti ... */
out_array[1] = num1[1] - num2[1]; /* + gestione riporti ... */
out_array[0] = num1[0] - num2[0]; /* + gestione riporti ... */


in num1[0] metto il valore intero di rapp[8],...,rapp[0]
in num1[1] metto il valore intero di rapp[17],...,rap[9]
in num1[2] metto il valore intero di rapp[19],...,rap[18]
ecc.


Giorgio Silvestri
Andre_Santarell
2006-07-24 19:43:22 UTC
Permalink
ciao, grazie per le vostre risposte.. volevo ora chiedervi la
"correzione" del programma che ho battuto insieme ad un amico



il programma purtroppo non funziona e io devo consegnarlo domani
mattina.. per favore, è urgentissimo, qualcuno potrebbe correggermi
gli errori ?

grazie mille
ciao



[code]
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define TERM 100

int main(int argc, char *argv[])
{
char num[21];
char num2[21];

printf("Inserisci il primo numero\n");
scanf("%s",&num);
printf("Inserisci il secondo numero\n");
scanf("%s",&num2);

//Inizio a copiare l'array char dentro un array int
unsigned int num_i[20];
unsigned int num_i2[20];

int pos;
char temp[2];
temp[1]='\0';
for (pos=0; pos<=20; pos++)
{
temp[0]=num[pos];
num_i[pos]=atoi(temp);
printf("%i\n",num_i[pos]);
}

temp[1]='\0';
for (pos=0; pos<=20; pos++)
{
temp[0]=num2[pos];
num_i2[pos]=atoi(temp);
printf("%i\n",num_i2[pos]);
}

int numero[20],numero2[20];
memset(numero,'0',sizeof(numero));
memcpy(numero+20-strlen(num),num_i,strlen(num));
memset(numero2,'0',sizeof(numero2));
memcpy(numero2+20-strlen(num2),num_i2,strlen(num2));

//Inizio la sottrazione
int cicle,int result[20];
for (cicle=20;cicle>=0;cicle--)
{
if( sizeof(numero2) > sizeof(numero) )
printf("Errore! Perfavore inserire prima il numero maggiore!\n");
exit 0;
if( numero[cicle] > numero2[cicle])
result[cicle] = numero[cicle] - numero2[cicle];
if( numero[cicle] < numero2[cicle])
{
numero[cicle-1]--;
numero[cicle] += 10;
result[cicle] = numero[cicle] - numero2[cicle];
}
if( numero[cicle] < 0)
printf("Errore!\n");
printf("Il risultato della sottrazione è: %i",reult);

return(0);
}

[/code]


:muro: :muro:
Giorgio Silvestri
2006-07-24 21:32:53 UTC
Permalink
Post by Giorgio Silvestri
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define TERM 100
int main(int argc, char *argv[])
{
char num[21];
char num2[21];
printf("Inserisci il primo numero\n");
scanf("%s",&num);
bastava scanf("%s",num);
Post by Giorgio Silvestri
printf("Inserisci il secondo numero\n");
scanf("%s",&num2);
bastava scanf("%s",num2);
Post by Giorgio Silvestri
file://Inizio a copiare l'array char dentro un array int
unsigned int num_i[20];
unsigned int num_i2[20];
int pos;
char temp[2];
temp[1]='\0';
for (pos=0; pos<=20; pos++)
perché <= ? vai fuori dell'array num_i[] !!!!
perché 20 ? strlen(num) !
Post by Giorgio Silvestri
{
temp[0]=num[pos];
num_i[pos]=atoi(temp);
bastava num_i[pos] = num[pos] - '0';
Post by Giorgio Silvestri
printf("%i\n",num_i[pos]);
}
temp[1]='\0';
for (pos=0; pos<=20; pos++)
{
temp[0]=num2[pos];
num_i2[pos]=atoi(temp);
printf("%i\n",num_i2[pos]);
}
idem.
Post by Giorgio Silvestri
int numero[20],numero2[20];
memset(numero,'0',sizeof(numero));
numero[] e numero2[] sono array di interi !!!
Con '0' non ottieni quello che pensi!!!
Post by Giorgio Silvestri
memcpy(numero+20-strlen(num),num_i,strlen(num));
memset(numero2,'0',sizeof(numero2));
memcpy(numero2+20-strlen(num2),num_i2,strlen(num2));
non funziona assolutamente per quanto detto.
Tutto il lavoro di memset andava fatto prima. Cioè subito
dopo l'input, sull'array num[] e num2[].
Non sugli array di interi ...
Post by Giorgio Silvestri
file://Inizio la sottrazione
int cicle,int result[20];
for (cicle=20;cicle>=0;cicle--)
{
if( sizeof(numero2) > sizeof(numero) )
e come potrebbe essere maggiore visto che li hai definiti uguali ?
Post by Giorgio Silvestri
printf("Errore! Perfavore inserire prima il numero maggiore!\n");
exit 0;
assolutamente no!
Il test non ha senso per decidere se due numeri sono uno maggiore
dell'altro.
Post by Giorgio Silvestri
if( numero[cicle] > numero2[cicle])
result[cicle] = numero[cicle] - numero2[cicle];
if( numero[cicle] < numero2[cicle])
{
numero[cicle-1]--;
numero[cicle] += 10;
result[cicle] = numero[cicle] - numero2[cicle];
}
if( numero[cicle] < 0)
printf("Errore!\n");
printf("Il risultato della sottrazione è: %i",reult);
?????

Ci sono troppi errori.
Devi spedire un codice direttamente compilato e non
un ulteriore copia manuale dai file sorgenti.
Siamo lontani dalla soluzione.

Eppure se partivi dai miei frammenti di codice, sopratutto per
l'input, l'esercizio era praticamente finito ...


--
Giorgio Silvestri

Loading...