Linguaggio D

Tipi base  - numeri             
 

Torniamo un attimo sui numeri in quanto strumento principe nel campo della programmazione: un approccio semplice per iniziare. Le operazioni base sono sempre le stesse e le illustriamo nel seguente esempio:

  Esempio 2b-1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import std.stdio;
import std.conv;
void main()
{
  write("Inserisci un numero: ");
  string s1 = readln();
  write("Inserisci un altro numero: ");
  string s2 = readln();
  int x1 = parse!int(s1);
  int x2 = parse!int(s2);
  writeln(x1 + x2);
  writeln(x1 - x2);
  writeln(x1 * x2);
  writeln(x1 / x2);
  writeln(x1 % x2);
  writeln(x1 ^^ x2);
}

Non c'è bisogno di troppe spiegazioni direi, almeno per la maggior parte dei simboli. Alla riga 14 abbiamo la divisione, alla 15 il resto da divisione, alla 16 l'elevamento a potenza, effettuato nel suo modo più semplice e funzionante anche con i numeri con virgola. Alla 2 abbiamo importato la libreria conv che ci permette di utilizzare il metodo parse che effettua la conversione da stringa ad intero. La prima cosa che sono solito notare in questi casi è che la divisione ci fornisce un risultato molto approssimativo, ad esempio inserendo i valori 7 e 3 otterreste come output alla riga 14, il numero 2. ma si, va bene, però il risultato corretto è 2,33333.... non due che è la parte intera e costituisce una approssimazione eccessiva. Se volete il risultato corretto partendo dagli interi non potrete ottenerlo e dovete ricorrere ad un cast, ovvero, per ora prendetelo così, ad una conversione volante di tipo che si esegue tramite la keyword, guarda un po', cast. Ovvero dovrete scrivere:

writeln(x1 / cast(float)x2);
oppure
writeln(cast(float)x1 / x2);

o, se volete, potete applicare il cast su entrambi i valori; il concetto è che dovete convertire almeno uno dei due operandi da intero in float, o double, o real. Dal punto di vista dell'output, usando le istruzione del programma 2b-1 potreste rimanere un po' delusi, visto che avrete 5 cifre decimali soltanto. Ad esempio inserendo il valore 20 per x1 e 3 per x2 otterrete:
6.66667
Se volete fare qualche test più preciso dovrete usare writelfln ovvero una forma di scrittura formattata; la sua descrizione ufficiale infatti è:
Writes its arguments in text format to the file, according to the format in the first argument, followed by a newline.
Vediamo quindi un ulteriore esempio in cui possiamo anche osservare le differenze che otteniamo scegliendo varie tipologia di numeri:

  Esempio 2b-2
1
2
3
4
5
6
7
8
9
10
11
import std.stdio;
void main()
{
  int x1 = 7;
  int x2 = 3;
  writeln(x1 / x2);
  writefln("%.20g", cast(float)x1 / x2);
  writefln("%.20g", cast(double)x1 / x2);
  writefln("%.20g", cast(real)x1 / x2);
  readln();
}

l'output è:

2
2.3333332538604736328
2.3333333333333334813
2.3333333333333333332
 

come si vede, il tipo real è quello che ha una maggior precisione (ed anche una maggior pesantezza.... nulla è gratis in questo mondo). La precisione è imposta sulle 20 cifre, lo si intuisce da quel "20" che trovate alle righe 7, 8 e 9. Ovviamente, vedremo più in dettaglio le opzioni di formattazione dell'output.

Questo linguaggio è provvisto anche di una potente libreria matematica che contiene una serie di funzioni pronte all'uso e anche alcune classiche costanti matematiche. Questa libreria, che si chiama math, può essere importata come le altre. Per saperne di più trovate tutte le informazioni del caso qui. Di seguito fornisco un semplice esempio d'uso:

  Esempio 2b-3
1
2
3
4
5
6
7
8
9
10
11
12
import std.stdio;
import std.math;
void main()
{
  float x1 = 7.1;
  float x2 = 3.4;
  writeln(PI);
  writeln(E);
  writeln(pow(x1, x2));
  writeln(sqrt(2.0));
  readln();
}

La riga 7 propone il classico pi greco, la 8 la costante euleriana (o neperiana), la 9 un ulteriore metodo di elevamento a potenza e la 10 la radice quadtata (che vuole come argomento un float). Fondamentale, come detto, è l'importazione della libreria, che avviene alla riga 2.