Divisione fra interi

Inviato:
22 feb 2018, 13:56
da EcoTan
Mi esprimo con un esempio.
Se facciamo 17 diviso 10 viene 1, col resto di 7 che è più della metà di 10.
Il 2 come quoziente non ci entrerebbe, ma per poco.
In linguaggio C facendo questa divisione fra variabili dichiarate come int, verrebbe 1 come risultato (sbaglio?).
Se facciamo -17 diviso 10 viene -1, col resto di -7.
In linguaggio C facendo questa divisione fra variabili dichiarate come int, verrebbe -1 come risultato (sbaglio? Non è che in questo caso verrebbe -2?).
Se prendessimo l'abitudine, tutte le volte che facciamo una divisione fra interi, di ritoccare il dividendo, se positivo aggiungendogli la metà del divisore, se negativo sottraendogli la stessa metà del divisore, non è che i calcoli verrebbero meglio arrotondati (mi riferisco in particolare al buon funzionamento dei filtri digitali)?
P.S. Nel caso del primo esempio sopra riportato, ritocchiamo il dividendo 17 aggiungendogli la metà del divisore cioè 5, quindi otteniamo 22 che diviso per 2 fornisce un quoziente pari a 2, approssimato per eccesso ma più vicino al risultato reale di quanto non sia il precedente quoziente pari ad 1.
Re: Divisione fra interi

Inviato:
22 feb 2018, 14:17
da IlGuru
Io farei un loop di sottrazioni
Re: Divisione fra interi

Inviato:
22 feb 2018, 14:40
da EcoTan
Funziona anche come arrotondamento? Comunque non mi sembra che sia una tecnica molto veloce.
Re: Divisione fra interi

Inviato:
23 feb 2018, 0:56
da GuidoB
EcoTan ha scritto:Se facciamo -17 diviso 10 viene -1, col resto di -7.
In linguaggio C facendo questa divisione fra variabili dichiarate come int, verrebbe -1 come risultato (sbaglio? Non è che in questo caso verrebbe -2?).
Fa' attenzione: la divisione tra numeri interi in C può dare un risultato diverso dalla divisione intera in altri linguaggi

.
Contrariamente a quanto sarebbe più prevedibile e matematicamente comodo da utilizzare, i risultati vengono troncati verso lo zero, non arrotondati all'intero inferiore. Quindi certi risultati pari a 0 o negativi possono aver bisogno di essere diminuiti di 1 prima di essere utilizzati in calcoli successivi.
Re: Divisione fra interi

Inviato:
23 feb 2018, 1:32
da xyz
Il C utilizza direttamente l'istruzione in linguaggio macchina della CPU selezionata per divide 2 interi (se disponibile) la quale non fa nessun arrotondamento, tronca sempre.
Se serve avere il valore del quoziente e resto la libreria C offre la funzione di libreria "div":
https://linux.die.net/man/3/divin base al segno del quoziente e al valore del resto è possibile arrotondare all'intero più vicino.
Esiste un metodo veloce per eseguire una divisione tra tipi segnati con arrotondamento all'intero più vicino nei casi con numeratore e denominatore positivi e/o negativi. Nei sorgenti del kernel di Linux nel file "include/linux/kernel.h" esiste la seguente macro (funziona col GCC, ignoro se funziona col altri compilatori):
- Codice: Seleziona tutto
...
/*
* Divide positive or negative dividend by positive or negative divisor
* and round to closest integer. Result is undefined for negative
* divisors if he dividend variable type is unsigned and for negative
* dividends if the divisor variable type is unsigned.
*/
#define DIV_ROUND_CLOSEST(x, divisor)( \
{ \
typeof(x) __x = x; \
typeof(divisor) __d = divisor; \
(((typeof(x))-1) > 0 || \
((typeof(divisor))-1) > 0 || \
(((__x) > 0) == ((__d) > 0))) ? \
(((__x) + ((__d) / 2)) / (__d)) : \
(((__x) - ((__d) / 2)) / (__d)); \
} \
)
...
Re: Divisione fra interi

Inviato:
23 feb 2018, 9:44
da EcoTan
Grazie. Dalle risposte vedo che le tecniche di arrotondamento all'intero più vicino vengono prese in considerazione, quindi penso di adottarle nel fare i calcoli.
Re: Divisione fra interi

Inviato:
23 feb 2018, 11:03
da EcoTan
Infatti quello era un esempio fatto allo scopo di esprimermi.
Nel caso pratico ho un accumulatore long int in cui sommo le letture di un segnale a 10 bit, e dopo ogni 2 letture tolgo dall'accumulatore 1/64 del suo valore (tutto ciò equivale ad amplificare il segnale 127 volte e filtrarlo con una costante di tempo pari a 128 volte l'intervallo fra le letture).
L'intenzione è quella di usare ambedue le tecniche, cioè il dividendo è già abbastanza grande e inoltre arrotondare la divisione per 64 all'intero più vicino.
e qui cade un altro problema: ho l'impressione che non basta dichiarare una variabile long int, poi bisogna specificare (long int) tutte le volte.
Re: Divisione fra interi

Inviato:
23 feb 2018, 12:24
da xyz
EcoTan ha scritto:L'intenzione è quella di usare ambedue le tecniche, cioè il dividendo è già abbastanza grande e inoltre arrotondare la divisione per 64 all'intero più vicino.
Se dividi con potenze di 2 poi non chiamare la divisione ma spostare i bit a destra con operatore ">>", per arrotondare puoi sommare prima dello right shift la meta' del divisore. Molti compilatori, se abilitate le ottimizzazioni, quando si divide per un numero costante potenza di 2 esegue questa ottimizzazione.
Quando si divide bisogna stare molto attenti tra i tipi con e senza segno e evitare di mischiare i tipi, se obbligati fare sempre prima un cast col tipo giusto.