View Full Version : logaritmi
Wilcomir
27-10-2005, 21:12
allora, io faccio la seconda liceo scientifico PNI, ma vorrei sapere qualcosa di più sui logaritmi. in particolare il problema che devo risolvere, e scrivere in java, è un programma che dato un numero mi restituisce il numero di byte necessari a memorizzarlo. in 1 byte ci stanno 256 combinazioni (2^8), in 2 byte 256*256, e così via. ora, se io conosco un numero, come faccio a risalire al numero di byte necessari? so che ci vogliono i logaritmi... booooh
ciao!
Fradetti
27-10-2005, 22:22
http://it.wikipedia.org/wiki/Logaritmo
Wilcomir
28-10-2005, 05:09
http://it.wikipedia.org/wiki/Logaritmo
grazie! oggi pomeriggio ci do un'occhiata... se ho domande/dubbi/perplessità non esiterò a chiedere :rolleyes:
ciao!
allora, io faccio la seconda liceo scientifico PNI, ma vorrei sapere qualcosa di più sui logaritmi. in particolare il problema che devo risolvere, e scrivere in java, è un programma che dato un numero mi restituisce il numero di byte necessari a memorizzarlo. in 1 byte ci stanno 256 combinazioni (2^8), in 2 byte 256*256, e così via. ora, se io conosco un numero, come faccio a risalire al numero di byte necessari? so che ci vogliono i logaritmi... booooh
ciao!
Non sono del settore, comunque direi che basta prendere il tuo numero (che chiamiamo X) e fare il logaritmo in base 256 di X arrotondato per eccesso.
Il ragionamento sottostante è questo: se il numeo è compreso tra 0 e 256, quanto spazio ti serve? Uno e la formula data ritorna un valore tra 0 e 1. Se il numero è compreso tra 256 e 256^2? Due, e la funzione ritorna un valore tra 1 e 2. Spero di essere stato chiaro.
Poi, nel caso non lo sapessi, il logaritmo in base 256 lo puoi ottere con il logaritmo in base qualsiasi in questo modo:
logaritmo di x in base 256= log in base qualsiasi di X / log in base qualsiasi di 256
Le basi a destra dell'uguale devono essere le stesse.
Spero di non aver detto minchiate, ma spero e credo proprio di no.
Ciao. :)
Wing_Zero
28-10-2005, 13:34
dai, la soluzione e' semplice :)
non serve logaritimi o che....
basta che dato un numero(es 10) lo trasformi in binario(es 1010).
poi allochi un numero di bit equivalente pari al numero di cifre del numero in binario. ed hai fatto ;)
Wilcomir
28-10-2005, 14:02
dai, la soluzione e' semplice :)
non serve logaritimi o che....
basta che dato un numero(es 10) lo trasformi in binario(es 1010).
poi allochi un numero di bit equivalente pari al numero di cifre del numero in binario. ed hai fatto ;)
ma come trasformare in binario? in java voglio dire... o magari c'è un metodo meccanico, ma devo scrivermelo?
ciao!
gurutech
28-10-2005, 19:34
chiamiamo log10(x) il logaritmo in base 10 di x e log2(x) il logaritmo in base 2 di x.
per una nota proprietà dei logaritmi
log2(x) = log10(x) / log10(2)
per trovare il numero di bit necessari a rappresentare un numero x si ha che
NBIT = eccesso( log2(x) ) = eccesso ( log10(x) / log10(2) )
dove con eccesso ho indicato l'operazione di arrotondamento per eccesso.
per trovare il numero di byte puoi dividere il numero di bit per 8 e arrotondare nuovamente, oppure come giustamente detto prima puoi fare il logaritmo in base 256
NBYTE= eccesso( log10(x) / log10(256) )
per Java non so che dirti ...
Wilcomir
28-10-2005, 20:26
ho risolto con poche righe di codice, scrivo anche uno pseudo codice per i meno pratici.
public int bytes (int num) {
String bynary = Integer.toBinaryString(num);
int bits = bynary.length();
int bytes = 0;
if (bits > 8) {
bytes = bits/8;
}
bytes++;
return bytes;
}
allora
metodo pubblico restituisce un intero "byte" e prende un intero "num" {
stringa "bynary" = valore binario di num; *fulcro del problema :)
intero "bits" = lunghezza di bynary;
intero bytes = 0;
se bits > 8 allora {
bytes = bytes/8;
}
bytes = bytes+1;
restituisci bytes;
}
ciao a tutti e grazie sopratutto a Wing_Zero, che mi ha dato l'imbroccata per fare qualcosa di carino... :D
ciao!
ho risolto con poche righe di codice, scrivo anche uno pseudo codice per i meno pratici.
public int bytes (int num) {
String bynary = Integer.toBinaryString(num);
int bits = bynary.length();
int bytes = 0;
if (bits > 8) {
bytes = bits/8;
}
bytes++;
return bytes;
}
allora
metodo pubblico restituisce un intero "byte" e prende un intero "num" {
stringa "bynary" = valore binario di num; *fulcro del problema :)
intero "bits" = lunghezza di bynary;
intero bytes = 0;
se bits > 8 allora {
bytes = bytes/8;
}
bytes = bytes+1;
restituisci bytes;
}
ciao a tutti e grazie sopratutto a Wing_Zero, che mi ha dato l'imbroccata per fare qualcosa di carino... :D
ciao!
C'è un problema col tuo programma: tu ricevi un numero intero di tipo elementare int, che occupa esattamente 4 byte: poi calcoli il numero di byte occupati "effettivamente" dal numero num, che non potrà che essere un numero compreso tra 1 (il minimo) e 4 (il massimo) byte... Sei sicuro che questo sia significativo, cioè che sia quello che ti interessa veramente?
Wing_Zero
29-10-2005, 13:09
ho risolto con poche righe di codice, scrivo anche uno pseudo codice per i meno pratici.
public int bytes (int num) {
String bynary = Integer.toBinaryString(num);
int bits = bynary.length();
int bytes = 0;
if (bits > 8) {
bytes = bits/8;
}
bytes++;
return bytes;
}
allora
metodo pubblico restituisce un intero "byte" e prende un intero "num" {
stringa "bynary" = valore binario di num; *fulcro del problema :)
intero "bits" = lunghezza di bynary;
intero bytes = 0;
se bits > 8 allora {
bytes = bytes/8;
}
bytes = bytes+1;
restituisci bytes;
}
ciao a tutti e grazie sopratutto a Wing_Zero, che mi ha dato l'imbroccata per fare qualcosa di carino... :D
ciao!
di niente :P :D
io programmo in C, il java non lo conosco... pero' se ti posso essere utile, ekkime qua :D
Wilcomir
29-10-2005, 13:43
allora il mio obbiettivo è ricever un numero intero e restituire i byte necessari a memorizzarlo, quindi invece di usare logaritmi e compagnia, visto che non ho la più pallida idea di cosa siano, se in java già ci sono e se no come implementarli, allora converto il numero in binario, che poi è come lo memorizza il pc, e guardo quanto è lunga la stringa. faccio la divisone per 8, e aggiungo 1 visto che con gli int se x/8=0,qualcosa lui mi da 0. mi sorge ora un dubbio, anzi vari:
la stringa che mi restituisce la funzione toBynaryString, è priva di spazi? e la misurazione della lunghezza, parte da 0 o da 1? boooooh...
ciao!
Wing_Zero
29-10-2005, 14:20
allora il mio obbiettivo è ricever un numero intero e restituire i byte necessari a memorizzarlo, quindi invece di usare logaritmi e compagnia, visto che non ho la più pallida idea di cosa siano, se in java già ci sono e se no come implementarli, allora converto il numero in binario, che poi è come lo memorizza il pc, e guardo quanto è lunga la stringa. faccio la divisone per 8, e aggiungo 1 visto che con gli int se x/8=0,qualcosa lui mi da 0. mi sorge ora un dubbio, anzi vari:
la stringa che mi restituisce la funzione toBynaryString, è priva di spazi? e la misurazione della lunghezza, parte da 0 o da 1? boooooh...
ciao!
allora
penso che vada bene quella funzione, pero' il java non lo conosco :P
la stringa che mi restituisce la funzione toBynaryString, è priva di spazi? e la misurazione della lunghezza, parte da 0 o da 1? boooooh...
Leggendo qui:
http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Integer.html#toBinaryString(int)
Direi che la stringa ha come lunghezza il numero di bit.
Come detto da Mixmar, il numero che puoi ottenere va da 1 a 4.
Considera che con 32 bit hai già 4294967296 valori codificabili; in genere con grossi numeri si preferisce fare delle valutazioni "spannometriche" (usando le proprietà degli esponenziali e dei fattoriali ad esempio).
ma gli int nn sono mica memorizzati sempre in 4 byte, riempiendo i bit prima del numero di zeri?
cmq venendo al punto, spieghiamo cos'è un logaritmo.
il logaritmo è composto da una base e da un argomento(log a (b) = logaritmo in base a(a si scrive come pedice di log) di b).
se ho che a^x=b, allora x = log a (b). in parole il logaritmo in base a di b è l'esponente da dare ad a per avere b.
gurutech
29-10-2005, 18:03
allora il mio obbiettivo è ricever un numero intero e restituire i byte necessari a memorizzarlo, quindi invece di usare logaritmi e compagnia, visto che non ho la più pallida idea di cosa siano, se in java già ci sono e se no come implementarli, allora converto il numero in binario, che poi è come lo memorizza il pc, e guardo quanto è lunga la stringa. faccio la divisone per 8, e aggiungo 1 visto che con gli int se x/8=0,qualcosa lui mi da 0. mi sorge ora un dubbio, anzi vari:
la stringa che mi restituisce la funzione toBynaryString, è priva di spazi? e la misurazione della lunghezza, parte da 0 o da 1? boooooh...
ciao!
il tuo metodo è corretto, ma un'esercizio del genere di solito è un classico per capire cosa è un logaritmo. Se andrai avanti nello studio ti accorgerai che il logaritmo è molto utile, per cui ti conviene sforzarti di implementare la funzione anche attraverso il log.
Non è possibile che Java(o qualsiasi altro linguaggio ad alto livello) non li abbia, per cui leggi il manuale :Prrr:
poi come per tutti i problemi di informatica ci sono n-mila modi per risolverli, alcuni puù brevi ed altri più lunghi, sia in termini di istruzioni che di cicli macchina!
ad esempio guarda questo modo che NON usa i logaritmi
x = numero da convertire
il codice è in C, ma ti ho evidenziato in rosso la parte fondamentale, che non dovrebbe essere difficile da convertire ad altri linguaggi
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int x,nbit,nbyte;
x=1000;
nbit=0;
nbyte=0;
while (x>=1) {
x=x/2;
nbit=nbit+1;
}
nbyte=1+nbit/8;
printf("nbit = %d * nbyte = %d\n",nbit,nbyte);
return 0;
}
}
in questo programma è fondamentale che le variabili siano INTERI
Wilcomir
29-10-2005, 18:46
io i logaritmi non li ho ancora fatti a scuola... comunque ecco i risultati con vari numeri:
1-------->1
255------>1
256------>2
65535---->3 ??
oh oh... c'è qualcosa che non quadra... :cry:
io i logaritmi non li ho ancora fatti a scuola... comunque ecco i risultati con vari numeri:
1-------->1
255------>1
256------>2
65535---->3 ??
oh oh... c'è qualcosa che non quadra... :cry:
con l'1 ok ci siamo ci vuole un byte : 00000001
con 255 ce ne vuole ancora 1 : 11111111
con 256 invece ce ne vogliono 2 : 00000001 00000000
con 65535 ce ne vogliono 2 nn tre : 11111111 11111111
l'ultimo devi aver sbagliato qualcosa perchè anche facendolo coi logaritmi viene
2^x=65535 ==> x=log2 (65535) = log 65535 / log 2 (la base in questo caso è quella dei logaritmi naturali, e, detto numero di nepero e pari a 2,718)
quindi viene 4.81/0.3 = 16 bit
infatti 2^17 = 65536 (1 00000000 00000000) quindi 65535 è il più grande numero possibile con 16 bit ((2^x)-1)
Wilcomir
30-10-2005, 05:53
infatti, ho provato proprio 65535 per vedere se faceva bene il cambio... comunque, ecco la nuova versione (che non ha nulla a che fare con la precedente):
public int bytes(long num) {
int bits = 0;
while (num > 1) {
num = num / 2;
bits++;
}
int bytes = 1 + (bits / 8);
return bytes;
}
la variabile long è sempre intera, ma quando la inizializza alloca uno spazio maggiore... non so quanto però. fattostà che ho qualche problema... ora vedo eh.
ciaoooo!
gurutech
30-10-2005, 08:58
ciao, effettivamente la versione che ti ho postato prima ha qualche problema ...
puoi correggere così:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(void) {
double x,nbit,nbyte;
x=256;
nbit=0;
nbyte=0;
while (x>=1) {
x=x/2;
nbit=nbit+1;
}
/* ceil fa l'arrotondamento per eccesso */
nbyte=ceil(nbit/8);
printf("nbit = %d * nbyte = %d\n",(int)nbit,(int)nbyte);
return 0;
}
oppure, se ti interessa solo il numero di byte così:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(void) {
int x,nbyte;
x=65536;
nbyte=0;
while (x>=1) {
x=x/256;
nbyte=nbyte+1;
}
printf("nbyte = %d\n",nbyte);
return 0;
}
naturalmente penso sempre che ti dovresti sforzare di imparare i logaritmi. anche se non te li ha ancora spiegati il prof. non sono difficili, prova a leggiucchiare qualcosa sul tuo libro di mate
edit
se non vuoi usare ceil puoi fare anche così:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int x,nbit,nbyte;
x=65536;
nbit=0;
nbyte=0;
while (x>=1) {
x=x/2;
nbit=nbit+1;
}
nbyte=nbit/8;
/* nbit % 8 è il resto della divisione tra nbit e 8 */
if (nbit % 8) nbyte=nbyte+1;
printf("nbit = %d * nbyte = %d\n",nbit,nbyte);
return 0;
}
gurutech
30-10-2005, 09:18
oppure se ti va puoi sempre usare una versione ridotta per tirar fuori il numero di bit
(questa però non te la spiego perchè stamattina mi sento un po' 'stardo)
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int x,b;
x=1000;
for (b=0;x;b++) x=x>>1;
printf("%d\n",b);
return 0;
}
a cosa serve l'istruzione
x=x>>1?
a cosa serve l'istruzione
x=x>>1?
Ma come, ha detto che non lo spiega e non lo spiega! :p
No, sto scherzando: l'istruzione x = x >> 1 serve per "shiftare" a destra i bit costituenti il valore di x. In pratica vengono traslati, dimodochè il primo (partendo da sinistra) diventi il secondo, il secondo il terzo e così via: in questo modo, l'ultimo bit (LSB) di x viene perso, e ne compare uno nuovo al posto del primo (MSB), (di solito) posto a 0.
gurutech
30-10-2005, 11:01
questa è la stessa cosa fatta interamente con i bitwise operator (operatori bit-a-bit)
quando si opera con i bit:
fare uno shift a destra di un bit equivale a dividere per 2
fare uno shift a destra di un bit equivale a moltiplicare per 2
inoltre se prendo un intero, esempio 192 e faccio 192 & 7 (192 AND 7, AND bit a bit), ottengo il resto della divisione per 8
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int num,b;
printf("inserisci un intero: ");
/* questo miniciclo continua a chiedere un
valore in ingresso finchè non si mette un numero intero */
while (! scanf("%d",&num)) scanf("%*s");
/* questo ciclo for continua a fare la divisione tra num e 2 con uno shift */
for (b=0;num;b++) num=num>>1;
/* stampa a video i bit e i byte */
printf("bit %d , byte %d\n",b,b&7?(b>>3)+1:b>>3);
return 0;
}
io l'ho fatto così
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
main ()
{
int num,x=0,max;
printf("inserisci il numero\n");
scanf ("%d",&num);
while (pow(2,x)<=num)
{
x=x+1;
}
printf("bit = %d byte = %d",x,x/8);
getch();
return 0;
}
gurutech
30-10-2005, 11:58
lo hai provato con un numero di ingresso minore di 128 ? ti ritorna 0 byte!
(il problema è quando fai la divisione per 8 tra interi)
e comunque il mio compilato risparmia 100 byte su disco :Prrr:
se un byte sono 8 bit, contavo che usando meno di 8 bit si usassero 0 byte, intesi come formati da 8 bit.
risparmia 100 byte su disco...azz ecco perchè mi si è riempito l'hdd quando ho compilato il mio anzichè il tuo :D
scherzo ovvio che il tuo è più compatto, io ho cominciato a programmare da pochissimo e le operazioni sui bit nn le conosco
ciao
tu dici che dovrei fare così quindi?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
main ()
{
int num,x=0,max;
printf("inserisci il numero\n");
scanf ("%d",&num);
while (pow(2,x)<=num)
{
x=x+1;
}
printf("bit = %d byte = %d",x,(x/8)+1);
getch();
}
gurutech
30-10-2005, 14:02
se un byte sono 8 bit, contavo che usando meno di 8 bit si usassero 0 tu dici che dovrei fare così quindi?
printf("bit = %d byte = %d",x,(x/8)+1);
no, quello è l'errore che ho fatto io nel primo post. devi arrotondare per eccesso
e cos'ho fatto io?
se hai ad esempio 11:8 che fa 1,38, la divisione intera ti da come risultato 1, ci aggiungi 1 ed hai 2, come se avessi arrotondato per eccesso.
cmq io nn ho ancora capito cosa intendi, se ci sono 7 bit per te è un byte o 0 byte?
gurutech
30-10-2005, 14:48
e cos'ho fatto io?
se hai ad esempio 11:8 che fa 1,38, la divisione intera ti da come risultato 1, ci aggiungi 1 ed hai 2, come se avessi arrotondato per eccesso.
cmq io nn ho ancora capito cosa intendi, se ci sono 7 bit per te è un byte o 0 byte?
se ci sono 7 bit devi usare 1 byte per allocarli!
con 9 bit 2 byte
con 17 bit 3 byte etc etc
quando ad esempio hai 16 bit, 16/8 = 2 e non ci devi aggiungere 1!!! per questo nelle versioni prec ho controllato il resto della divisione per 2
comunque per me il modo didatticamente più corretto è
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(void) {
float num;
int nbit,nbyte;
printf("inserisci un numero: ");
scanf("%f",&num);
/* fa il logaritmo in base 2 di num,
lo arrotonda per difetto e aggiunge 1 */
nbit=1+(int)floor(log10(num)/log10(2));
/* come sopra ma base 256 */
nbyte=1+(int)floor(log10(num)/log10(256));
printf("%d %d\n",nbit,nbyte);
return 0;
}
l'unica nota sono quei cast a int evidenziati in rosso
nbit=1+(int)floor(log10(num)/log10(2));
nbyte=1+(int)floor(log10(num)/log10(256));
riesci a spiegarmi cosa fanno?
grazie ciao
gurutech
30-10-2005, 18:33
andiamo per pezzi
log10(num) è il logaritmo in base 10 del numero da convertire
per una nota proprietà dei logaritmi
log10(num)/log10(2) è il logaritmo in base 2 del numero
log10(num)/log10(256) è il logaritmo in base 256 del numero
floor() è l'arrotondamento per difetto
(int) è un type cast: fa diventare il valore di floor un numero di tipo int
prendiamo un esempio numerico noto: num = 255 , in binario 11111111
log10(255)/log10(2)=7.99.....
floor(7.99...) = 7
1+7 = 8 ---> numero di bit usati
log10(255)/log10(256)=0.999....
floor(0.999...) = 0
1+0 = 1 ---> numero di byte usati
con num = 256 , binario 100000000
log10(256)/log10(2)=8.0 (esatto)
floor(8.0) = 8
1+8 = 9 ---> numero di bit usati
log10(256)/log10(256)=1 (ovvio!)
floor(1) = 1
1+1 = 2 ---> numero di byte usati
spero di essere stato chiaro ....
la funzione log è contenuta in math.h?
grazie della spiegazione, nn conoscevo ne il cast ne il floor. il cast si può usare anche con i tra char e int ad esempio?
del tipo (int)c con c char mi ridà il numero ascii e viceversa?
gurutech
30-10-2005, 19:53
log10 e log fanno parte di math.h
per il C i char sono già dei numeri compresi tra 0 e 255 (8 bit) come puoi vedere da questo esempio:
#include <stdio.h>
int main(void) {
char p;
/* assegno il carattere spazio a p */
p=' ';
/* stampa il codice ASCII corrispondente allo spazio: 32 */
printf("%d\n",p);
/* stampa uno spazio */
printf("%c\n",p);
/* moltiplica spazio * 2 e aggiunge 1 = 65 ---> in ASCII corrisponde ad 'A' */
printf("%c\n",p*2+1);
}
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.