PDA

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!

TriacJr
28-10-2005, 06:41
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!

Mixmar
29-10-2005, 09:04
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

Banus
29-10-2005, 14:27
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).

Guts
29-10-2005, 16:57
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:

Guts
29-10-2005, 18:59
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;
}

Guts
30-10-2005, 09:29
a cosa serve l'istruzione

x=x>>1?

Mixmar
30-10-2005, 10:14
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;
}

Guts
30-10-2005, 11:51
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:

Guts
30-10-2005, 13:04
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

Guts
30-10-2005, 14:05
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

Guts
30-10-2005, 17:16
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 ....

Guts
30-10-2005, 19:36
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);
}