Javascript
   

Numeri                  

Ed eccoci, secondo uno schema consueto, a parlare del tipo che viene più usato nell'ambito della programmazione, ovvero i numeri.
La notizia secondo me buona è che in Javascript tutti i numeri sono di un unico tipo, non esistono int, uint, int64, long, float... è tutta una sola grande famiglia.

5
5.0
6.789
0x56
070
081

Tutti questi esempi appartengono ad un unico tipo. Il quarto esempio è un esadecimale, il quinto è un ottale, in quanto 0 è considerato prefisso per tale tipologia di rappresentazione. L'ultimo esempio però è 81 a tutti gli effetti, non può essere un ottale in quanto c'è la cifra 8 di mezzo e come  noto la rappresentazione ottale prevede solo le cifre da 0 a 7. Ecco un semplice esempio che potete far girare senza difficoltà:

  Esempio 4.1
1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
<head><title>test</title></head>
<body>
<script type="text/javascript">
var x = 4;
var y = 5
alert(x + y);
var z = 0xe;
var t = 0x2;
alert(z + t);
</script>
</body>
</html>

La loro rappresentazione in output è comunque in formato decimale. Bene, ma se i numeri sono tutti "uguali" ai nostri occhi, come sono rappresentati internamente? La cosa è semplice: in Javascript essi sono floating point in doppia precisione, rappresentati su 64 bit, di cui, come di consueto, 52 per la mantissa, 11 per l'esponente ed uno per il segno. Il range che va da ±5e-324 (negativo) a ±1.7976931348623157e+308 (positivo) che di per se abbastanza ampio per moltissimi scopi. Agire al di fuori di esso darà origine all'intervento di uno speciale valore -Infinity (negativo) o Infinity (positivo). Per quanto riguarda gli interi tuttavia il range va da −9007199254740992 (−2^53 ) a 9007199254740992 (2^53), estremi inclusi se vi serve saperlo, al di là di questi valori si ha una perdita di precisione. Vediamo ora un esempio:

  Esempio 4.2
1
2
3
4
5
6
7
8
9
10
<html>
<head><title>test</title></head>
<body>
<script type="text/javascript">
document.write(Number.MAX_VALUE);
document.write("</br>");
document.write(Number.MIN_VALUE);
</script>
</body>
</html>

Nell'esempio 4.2 abbiamo usato le costanti MAX_VALUE e MIN_VALUE che rappresentano i valori estremi possibili. Si tenga presente che, a livello di precisione, per gli interi si considera valido il limite di 15 cifre. Questo è evidente se provate a mandare in esecuzione le seguenti istruzioni:

var x = 999999999999999;
var y = 9999999999999999;
document.writeln(x);
document.writeln(y);

affinchè la richiesta di andare a capo espressa tramite writeln invece di write dovrete racchiudere lo script in una sezione <PRE>...</PRE>. Noterete subito che y viene approssimato come:
10000000000000000
questo conferma l'approssimazione.
Per i numeri con virgola la precisione presunta e di 17 cifre ma anche qui bisogna andare coi guanti, come vedremo tra poco. Per prima cosa dobbiamo imparare che i numeri con virgola devono avere il punto come separatore tra la parte intera e quella decimale e che dopo questo deve esserci una cifra significativa. Es:

1.     // non è un floating point
2.3    // va bene
5.667  // va bene
.889   // va bene ma non è raccomandato.
12.0   // è visto anche lui come intero

Detto questo notiamo che:

var x = 0.2;
var y = 0.1;
document.writeln(x + y);

Questo esempio dà come risultato:

0.30000000000000004

che non è esattamente quello ci si aspetta. Per aggirare questo problema si può operare come segue (non bello ma insomma...)

document.writeln((x * 10 + y * 10) / 10);

è ammessa anche la e-notazione:

var x = 1.234e10; // equivale a var x = 12340000000;

anche per i numeri negativi vale la stessa cosa con una osservazione che faccio giusto per evitare qualcuno perda del tempo per cercare la risposta ad un comportamento apparentemente incoerente:

var x = 3e-8; equivale a x = 0.00000003;
mentre var y = 3e-04; a y = 0.0003;.
Tuttavia se scriviamo, ad esempio document.write(x) o document.write(y) otteniamo nel primo caso 3e-8 come output, nel secondo 0.0003. Questo perchè ECMA vuole che laddove vi siano almeno 6 zeri precedenti la cifra significativa sia imposta la e-notazione. Formalmente infine, come formato generale, abbiamo:

[cifre][.cifre][(E|e)[(+|-)]cifre]

legate ai numeri sono anche 3 interessanti, possiamo definirle, un po' impropriamente, costanti:

NEGATIVE_INFINITY
POSITIVE_INFINITY
NaN

I primi due, come si può bene capire, li incontriamo quando andiamo al di là dei limiti imposti da MIN_VALUE e MAX_VALUE, provate a manipolare questi valori, ad esempio sommando qualcosa a MAX_VALUE. E' interessante ed importante che i valori infiniti sono gestibili e ciò costituisce un elemento importante ad esempio durante certi tipi di computazione.
Invece NaN è qualche cosa di nuovo, e sta per "Not a number". Esso viene richiamato quando ad esempio una qualche operazione ci restituisce un valore incompatibile con l'ambito numerico. NaN è un valore davvero particolare che ha la peculiarità di non essere uguale a niente, nemmeno a se stesso, in pratica
NaN == NaN è falso.
Per ottenere un NaN basta ad esempio un'istruzione tipo:
var x = Math.abs("www");
torneremo presto su quel "Math.abs". In alternativa un bello 0/0 va bene lo stesso per lo scopo.

Una particolarità che potete usare, non so in che occasione, è quella di poter rappresentare un numero in varie basi, usando Tostring, che converte, appunto, un numero (e anche altri elementi ma vedremo più avanti), si veda il seguente frammento di codice che potete usare come base per le vostre prove:

 var x = 2456;
document.write("base 2 " + x.toString(2) + "<br />");
document.write("base 7 " + x.toString(7) + "<br />");
document.write("base 16 " + x.toString(16) + "<br />");

La manipolazione a livello di operazioni di base non offre nessuna particolarità:

+  per l'addizione
-  per la sottrazione
*  per la moltiplicazione
/  per la divisione
%  per ricavare il resto di una divisione

L'esempio conferma la banalità della cosa:

  Esempio 4.3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<html>
<head>
<title>test</title>
</head>
<body>
<script type="text/javascript">
var x = 10;
var y = 7;
var z = 0xf
document.writeln(x + y + z + '<br>');
document.writeln(x - y + '<br>');
document.writeln(x * z + '<br>');
document.writeln(x / y + '<br>');
document.writeln(x % y + '<br>');
</script>
</body>
</html>

La divisione restituisce il risultato "reale" e non la solita approssimazione (come è logioco, visto che i numeri sono float, come abbiamo già detto). Se vi chiedete come fare per ottenere la parte intera di una divisione esistono un paio di metodi, prendeteli così come sono:

var x = 7;
var y = 3;
document.writeln(~~(x / y) + '<br>');
document.writeln(Math.trunc(x / y) + '<br>');

Una cosa che va ricordata è che Javascript è un linguaggio un po' lasco su alcuni aspetti. Il +, ad esempio,, come si può dedurre anche dai vari esempi in questo paragrafo, non serve solo per la somma di numeri ma anche per la concatenazione di stringhe. Il punto è che mentre nei linguaggi a forte tipizzazione non è possibile effettuare dei miscugli, qui si rischiano dei piccoli disastri se non fate un minimo di attenzione e questo perchè la concatenazione è prevalente sulla somma. In pratica:

E' possibile anche adoperare gli operatori seguenti:

+= ovvero x += y equivale a x = x + y
-= ovvero x -= y equivale a x = x - y
*= ovvero x *= y equivale a x = x * y
/= ovvero x /= y equivale a x = x / y
%= ovvero x %= y equivale a x = x % y
++ ovvero x ++ y equivale a x = x + 1
-- ovvero x -- y equivale a x = x - 1

Un problema che si incontra spesso, anche qui comune a tanti linguaggi, è quello della conversione da stringa a numero. Frequentemente infatti i dati vengono forniti tramite stringhe in input (direttamente da tastiera o, come è più probabile in Javascript, ricavandolo da file o database) e queste stringhe possono rappresentare dei numeri. La conversione avviene tramite una funzione dal nome abbastanza indicativo parseInt che accetta in input la stringa e, se tutto va bene, ovvero non vi sono errori nel formato della stringa, restituisce in output il numero. Di seguito presento qualche esempio, vale la pena fare qualche test da soli per allargare la casistica. La sintassi da usare è:

parseInt(stringa, base)

dove il secondo paramentro indica la base nella quale si vuole rappresentare il numero. Tale secondo parametro è opzionale ma il mio consiglio è quello di usarlo sempre, per uniformità. Il default è naturalmente la base 10, come si può evincere anche dall'esempio che segue, potrete ovviamente integrarlo con quel vi pare:

  Esempio 4.4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html>
<head><title>test</title></head>
<body>
<script type="text/javascript">
document.writeln(parseInt('aa') + '<br>');     // NaN
document.writeln(parseInt('aa', 16) + '<br>'); // 170 'a' è ok in esadecimale
document.writeln(parseInt('77', 8) + '<br>');  // 63
document.writeln(parseInt('101', 2) + '<br>'); // 5
document.writeln(parseInt('88', 8) + '<br>');  // NaN c'è 8 e siamo in base 8
document.writeln(parseInt('100') + '<br>');    // 100, base 10 è default
document.writeln(parseInt('1.234') + '<br>');  // 1
document.writeln(parseInt('066') + '<br>');    // 54 con lo 0 davanti è ottale

</script>
</body>
</html

Analogamente si può effettuare un parsing verso i float, attraverso parseFloat che prevede, come parametro, solo la stringa sulla quale effettuare il parsing come input, la conversione è sempre verso base 10 ed anche in questo caso è possibile ottenere un NaN se la stringa in input non ha il formato corretto.

  Esempio 4.5
1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
<head><title>test</title></head>
<body>
<script type="text/javascript">
document.writeln(parseFloat('aa') + '<br>'); // NaN
document.writeln(parseFloat('10') + '<br>'); // 10
document.writeln(parseFloat('1.2345') + '<br>'); // 1.2345
document.writeln(parseFloat('1.2a') + '<br>'); // 1.2
document.writeln(parseFloat('212e-3') + '<br>'); // 0.212
document.writeln(parseFloat('09') + '<br>'); // 9, niente ottale
</script>
</body>
</html

Dobbiamo, per completezza, parlare infine del numero inteso come "oggetto". Normalmente non vi capiterà di avere a che fare direttamente con questo chiamiamolo aspetto dei numeri ma è bene sapere che cosa c'è dietro. L'oggetto numero non è altro che un wrapper, un contenitore, per i numeri come li conosciamo. C'è un certo potenziale, quindi, che sta dietro, nascosto dietro l'apparenza. Come ogni oggetto che si rispetti anche il numero è dotato delle sue proprietà e dei suoi metodi. Degli oggetti parleremo a suo tempo, tra un bel po', ma tale natura  può essere evidenziata dalla seguente istanziazione:

var n = new Number(3);

ecco fatto, proprio come scrivere var n = 3; nè più nè meno. Ovviamente tutti preferiamo quest'ultimo modo di dichiarare una variabile numerica. Vediamo ora le proprietà, che peraltro abbiamo già incontrato:

-- MAX_VALUE
-- MIN_VALUE
-- NEGATIVE_INFINITY
-- POSITIVE_INFINITY
-- NaN

che evidentemente restituiscono i valori relativi. I metodi, anch'essi facilmente interpretabili, sono i seguenti, almeno quelli principali:

METODO DESCRIZIONE
toExponential converte il numero nella notazione esponenziale
toFixed formatta il numero con un prefissato numero di cifre dopo il punto decimale
toLocaleString visualizza il numero evidenziando caratteristiche "regionali"
toPrecision formatta il numero ad una lunghezza prefissata
toSource restituisce il codice usato per definire il numero (funzione di sicuro solo su FireFox)
toString converte il numero in formato stringa
valueOf restituisce il valore del numero

Ed ecco l'esempio:

  Esempio 4.6
1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
<head><title>test</title></head>
<body>
<script type="text/javascript">
var n = new Number(3.1415926);
document.writeln(n.toExponential() + '<br>');
document.writeln(n.toFixed(3) + '<br>');
document.writeln(n.toPrecision(10) + '<br>');
// document.writeln(n.toSource()); // ricordate: solo con FireFox
document.writeln(n.valueOf() + '<br>');
</script>
</body>
</html

Terminiamo questo paragrafo parlando di quel Math che avevamo visto all'inizio. Si tratta di un altro interessante oggetto che mette a disposizione molte funzionalità di tipo matematico. Queste saranno chiare attraverso la loro esposizione:

PROPRIETA' DESCRIZIONE
E restituisce la costante e (2,71828182845904590....)
LN2 restituisce il logaritmo naturale di 2
LN10 restituisce il logaritmo naturale di 10
LOG2E restituisce il logaritmo in base 2 di e
LOG10E restituisce il logaritmo in base 10 di e
PI restituisce il celeberrimo pi-greco
SQRT1_2 restituisce la radice quadrata di 1/2
SQRT2 restituisce la radice quadrata di 2
METODI DESCRIZIONE
abs(x) restituisce il valore assoluto di x
acos(x) restituisce l'arcocoseno di x
asin(x) restituisce l'arcoseno di x
atan(x) restituisce l'arcotangente di x
atan2(x,y) restituisce l'arcotangente di x/y
ceil(x) restituisce l'arrotondamento di x all'intero maggiore più vicino
cos(x) restituisce il coseno di x
exp(x) restituisce e^x
floor(x) restituisce l'arrotondamento di x all'intero minore più vicino
log(x) restituisce il logaritmo naturale di x
max(x,y,z,....,n) restituisce il massimo dei numeri tra parentesi
min(x,y,z,...,n) restituisce il minore dei numeri tra parentesi
pow(x,y) restituisce x^y
random() restituisce un numero random tra 0 e 1
round(x) restituisce l'intero più vicino a x
sin(x) restituisce il seno di x
sqrt(x) restituisce la radice quadrata di x
tan(x) restituisce la tangente di x

Come si può vedere ci sono molte funzione di base ed anche alcuni valori costanti che non userete mai nella vostra vita :-). Comunque qui si seguito fornisco un esempio meramente informativo, non sarà difficile farsi un esempio valido per tutti i metodi e tutte le proprietà visto che il loro uso è decisamente banale. Da notare che Math non ha costruttori e i suoi metodi e le  su proprietà devono essere richiamati esplicitamente tramite la classe stessa. Anche qui mostro, per concludere questo corposo paragrafo, un esempio, anche se l'uso di questa libreria dovrebbe già essere più o meno chiaro:

  Esempio 4.7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html>
<head><title>test</title></head>
<body>

<script type="text/javascript">
var x = Math.PI;
var y = Math.E;
document.writeln(Math.PI + '<br>');
document.writeln(Math.E + '<br>');
document.writeln(Math.max(2,3) + '<br>');
document.writeln(Math.pow(2,3) + '<br>');
document.writeln(Math.random());
</script>

</body>
</html>