Press "Enter" to skip to content

4 Absolute Beginners – Le operazioni aritmetiche di base

4 Absolute Beginners – Le operazioni aritmetica di base

Livello: principianti
Prerequisiti: aver completato le lezioni precedenti

Operatori e punteggiatura

Nella lezione sugli identificatori, abbiamo introdotto l’operatore . (dot) ovvero il Member Access Operator, scrivendo il codice di test dell’ hello world e del progetto di visualizzazione delle variabili, abbiamo anche introdotto ed utilizzato l’ operatore ; (semicolon) che è il terminatore di istruzione. infatti salvo alcune cose particolari, ogni istruzione C# termina con un ; (punto e virgola o semicolon). Abbiamo anche utilizzato l’operatore = (equal) operatore di assegnazione, per assegnare valori alle proprietà degli oggetti negli esempi precedenti.

Nella lezione precedente, dove non ho dato spiegazione in merito perché non era il focus di quella lezione abbiamo anche utilizzato l’operatore + (plus) per comporre delle stringhe. Abbiamo sommato delle stringhe. C# nella descrizione del linguaggio contiene molti segni di punteggiatura, che sono utilizzati per costruirne la sintassi. li introdurremo pian piano, in questa e nelle lezioni successive, mentre impariamo i fondamentali per creare una applicazione.

Se volete vederli tutti, potete leggere C# Operators su MSDN dove sono elencati e spiegati tutti quanti noi li introdurremo nelle varie lezioni quando li utilizzeremo. In questa lezione parleremo di Aritmetica di base  e aggiungeremo una spiegazione un po’ più dettagliata riguardo l’operatore di addizione delle stringhe.

Prima di iniziare a parlare dei nostri operatori, creiamo un nuovo progetto dove scriveremo il codice di esempio e creeremo una mini applicazione per fare le 4 operazioni.

basemath_project_minicalc_01[10]

In Visual Studio 2015, New Project (Nuovo progetto), selezioniamo Visual C#, WPF Application, Chiamiamo il progetto MiniCalc, la soluzione BaseMath. E diamo OK.

L’operatore + (plus) addizione

L’operatore di addizione, esattamente come in tutte le nostre calcolatrici, permette di sommare numeri, pertanto potete applicarlo a tutti i tipi di dati numerici di base che abbiamo listato nella precedente lezione. Facciamo un paio di esempi di codice:

int integer1 = 3280;
int integer2 = 5420;
int integerResult = integer1 + integer2;
ulong unsignedLong1 = 7890000000;
ulong unsignedLong2 = 389000000000;
ulong unsignedLongResult = unsignedLong1 + unsignedLong2;
float floatingpoint1 = 12.789f;
float floatingpoint2 = 7953.17f;
float floatingpointResult = floatingpoint1 + floatingpoint2;

Abbiamo scritto 3 addizioni su 3 tipi diversi di dati, quando visualizzeremo il risultato su schermo otterremo i seguenti risultati:

3280 + 5420 = 8700
7890000000 + 389000000000 = 396890000000
12,789 + 7953,17 = 7965,959

Come possiamo notare, le addizioni in C# non sono complicate. In questo esempio abbiamo creato delle variabili e visto come inizializzarle con un valore o usarle come risultato delle nostre addizioni. In C# valgono tutte le regole dell’aritmetica di base, pertanto potete ovviamente utilizzare più di due addendi, potete utilizzare più operatori nella stessa espressione, potete usare le parentesi tonde per modificarne la precedenza, gli operatori aritmetici seguono le regole di base imparate a scuola pertanto:

totale = 12 +8 *3 + 2

Verrà eseguita prima la moltiplicazione e poi le addizioni.

totale = (12 + 8) * (3 + 2)

verranno eseguite prima le addizioni e poi la moltiplicazione.

L’operatore – (minus) sottrazione

integerResult = integer1 - integer2;
unsignedLongResult = unsignedLong1 - unsignedLong2;
floatingpointResult = floatingpoint1 - floatingpoint2;

La sottrazione, come l’addizione (e presumo possiate immaginare le altre operazioni di base) è effettuata semplicemente ponendo il – (meno) fra i due operandi però, visualizzando il risultato di queste tre operazioni, il risultato non sarà quello che potremmo aspettarci.

3280 - 5420 = -2140
7890000000 - 389000000000 = 18446743692599551616
12,789 - 7953,17 = -7940,381
	  

Infatti, se per l’intero e il floating point il risultato è corretto, per l’unsigned long, il risultato è strano, ma non più di tanto, perché una sottrazione ha dato un valore cosi assurdo? proprio perché si tratta di un intero senza segno, il segno in una variabile intera è espresso portando a 1 il bit più significativo di quelli che compongono la variabile, pertanto nel caso dell’ unsigned long, la sottrazione da origine ad un numero negativo che però, non può essere espresso come tale perché la variabile non ha segno, quindi il sistema aggiunge al valore 2 elevato alla 64 il che sommato al valore risultante, produce quel numero orribile. Da questo si evince una raccomandazione importante: Quando si tratta di aritmetica e matematica, il programmatore deve fare particolare attenzione a quello che scrive.

L’operatore * (star) moltiplicazione

integerResult = integer1 * integer2;
unsignedLongResult = unsignedLong1 * unsignedLong2;
floatingpointResult = floatingpoint1 * floatingpoint2;

Come per gli operatori precedenti, la moltiplicazione è un operazione elementare e basilare, c’è qualcosa di cui tener conto quando si esegue? Una sola cosa importante, che comunque riguarda anche le altre operazioni, fate attenzione che la variabile in cui memorizzerete il risultato sia sufficientemente capiente, infatti, se il valore del risultato fosse maggiore della capienza della variabile, verrebbe sollevata un eccezione. Quindi, oltre ad essere ben coscienti di quale tipo di variabile usare in base agli addendi che ci aspettiamo, è importante decidere il tipo di variabile in base al massimo valore che ci aspettiamo di ricevere.

3280 * 5420 = 17777600
7890000000 * 389000000000 = 7050483764214431744
12,789 * 7953,17 = 101713,1  

L’operatore / (slash) divisione

integerResult = integer2 / integer1;
unsignedLongResult = unsignedLong2 / unsignedLong1;
floatingpointResult = floatingpoint2 / floatingpoint1;
5420 / 3280 = 1
389000000000 / 7890000000 = 49
7953,17 / 12,789 = 621,8759  

Rispetto agli altri operatori, l’ operatore di divisione, in C# (e in tutti i linguaggi di programmazione) ha un comportamento che è legato al tipo di dato, e se l’avviso riguardo la capienza rimane valido, è importante anche ricordare che se facciamo una divisione fra interi, il risultato sarà l’intero che rappresenta il risultato intero della divisione, non si tiene in alcun conto il resto, pertanto, se il divisore è meggiore del dividendo, il risultato sarà zero. Altra cosa importantissima, se effettuate una divisione per zero, verrà sollevata un eccezione (è il comportamento standard di tutti i computer) quindi quando scrivete codice per cui la divisione viene effettuata fra numeri ottenuti da un elaborazione, controllare che il divisiore non sia zero è compito del programmatore.

Il fatto che la divisione degli interi non tenga conto del resto, è quello che ha fatto nascere il prossimo operatore.

L’operatore % (module) resto

Questo operatore è applicabile a tutti i tipi di dati, ma non ha molto senso anche se funziona correttamente, sui valori di tipo floating point.

integerResult = integer2 % integer1;
unsignedLongResult = unsignedLong2 % unsignedLong1;

Applicando questo operatore, si ottiene il resto della divisione intera del primo operando per il secondo.

5420 % 3280 = 2140	
389000000000 % 7890000000 = 2390000000  

E’ un operatore che nella mia esperienza è tornato molto utile nelle operazioni di calcoli su date, ore, minuti, quindi calendari, oppure cartellini e timbrature, rilevamento di tempi eccetera.

L’operatore + applicato alle stringhe

Abbiamo visto nella lezione precedente che io ho fatto, senza spiegarvelo, una operazione di somma fra stringhe.

Result.Text = "Posso" + "Sommare" + "Delle stringhe";

La precedente riga di codice, è assolutamente lecita e legale, e ci permette di introdurre un concetto fondamentale di C# il concetto dell’ implementazione degli operatori fra oggetti diversi dai tipi numerici di base.

Nel C#, il programmatore può implementare qualsiasi operatore all’interno di una classe nel modo che considera più utile ai propri scopi. Nel caso delle stringhe, l’operatore + (plus)  implementa una concatenazione fra le stringhe, quindi date due variabili stringa come operandi, il risultato dell’addizione è una nuova stringa che contiene una stringa che è la somma delle due precedenti. Ecco perché, nella mia implementazione basica degli operatori nel codice della classe di test troverete il codice qui sotto riportato:

Result.Text = "\r\n" + integer1.ToString() + " + " + integer2.ToString() + " = " + integerResult.ToString();

Che origina la seguente stringa:

3280 + 5420 = 8700

Credo abbiate notato tutti quanti, che anche nella precedente lezione, pur non avendolo spiegato, quando ho trasformato delle variabili numeriche in stringa ho utilizzato la notazione identificatore.ToString(), cosa ho fatto scrivendo questa istruzione? ho semplicemente chiamato il metodo ToString della classe int nel caso della riga qui sopra scritta o quello della classe dell’identificatore utilizzato. In C# tutti gli oggetti, strutture o classi che siano, implementano un metodo ToString, che se implementato, secondo le regole indicate dalle linee guida, dovrebbe rappresentare lo stato dell’oggetto nel momento in cui viene chiamato.

Quindi, le classi del framework int, long, float eccetera, quando chiamiamo il loro metodo ToString ci restituiscono una stringa contenente la rappresentazione del numero che è in loro contenuto. Vedremo quando parleremo delle classi numeriche, come ToString abbia anche la possibilità di formattare il valore visualizzato in modo da ottenere una rappresentazione ad esempio in formato valuta quindi con i punti e le virgole. Inoltre è in grado di interpretare i separatori delle migliaia e dei decimali in base alla cultura locale così che in Italia i punti separino le migliaia e le virgole i decimali, mentre in zona anglosassone è il contrario.

Due piccoli, ma importanti operatori

Oltre agli operatori aritmetici di base, siccome molto spesso può succedere di dover contare incrementando una variabile C# ha ereditato da C due speciali operatori:

++ l'operatore incremento
-- l'operatore decremento

Questi operatori possono essere utilizzati per incrementare di 1 o decrementare di 1 una variabile intera.

int i = 0;
i++;
++i;

L’operatore incremento è un operatore unario, ovvero ha bisogno di un solo operando, a cui viene applicato l’incremento. le due operazioni qui sopra equivalgono a:

i = i + 1;
i = 1 + i;

Perché l’operatore di incremento può stare a destra o a sinistra dell’operando e soprattutto questo cambia il suo comportamento? Si ovviamente.

se l’operatore precede l’operando, l’operazione viene valutata per prima quando si trova (come di solito è) all’interno di una espressione. Se l’operatore si trova dopo l’operando l’operazione viene valutata dopo che il valore dell’operando è stato valutato. Cosa significa tutto questo a livello di codice? Lo vediamo con un esempio:

int i = 0;
Result.Text = Result.Text + "\r\n increment operator i=0 ++ " + i.ToString() + " i++  the value of i is: " + (i++).ToString();
Result.Text = Result.Text + "\r\n increment operator i=1 ++ " + i.ToString() + " ++i  the value of i is: " + (++i).ToString();

Il risultato di quanto scritto qui sopra è la seguente serie di stringhe:

increment operator i = 0++ 0 i++ the value of i is: 0
increment operator i = 1++ 1 ++i the value of i is: 2

Come potete vedere, nella prima riga, quando l’incremento segue la variabile, viene prima valutata l’espressione ToString() e poi viene fatto l’incremento, pertanto il valore visualizzato è zero.
Nella seconda riga, quando l’incremento precede la variabile, viene prima valutata l’espressione di incremento e poi il ToString, quindi il valore visualizzato è due.

int i = 0;
--i;
i--;

L’operatore decremento si comporta allo stesso modo.

int i = 0;
Result.Text = Result.Text + "\r\n decrement operator i=0 -- " + i.ToString() + " i-- the value of i is: " + (i--).ToString();
Result.Text = Result.Text + "\r\n decrement operator i=1 -- " + i.ToString() + " --i the value of i is: " + (--i).ToString();

Il risultato dell’operazione qui sopra è il seguente:

decrement operator i = 0--  0   i--  the value of i is: 0
decrement operator i = 1-- -1  --i  the value of i is: -2

Anche nel caso dell’operatore di decremento se l’operatore precede l’operando, viene valutata per prima l’espressione di decremento.

Perché questi operatori? Principalmente per l’uso nei cicli for che vedremo nelle prossime lezioni.

Una mini calcolatrice

Anche se questi articoli sono destinati a chi non ha ancora mai scritto software, considerato che sono noiosi altrimenti, anche se probabilmente non conoscete metà delle cose che faremo, ho deciso di mostrarvi quanto è facile fare un programma per creare una mini calcolatrice che applica le 4 operazioni a due numeri inseriti dall’utente. Per realizzare questo programma, modificheremo la MainWindow del progetto che abbiamo creato qualche paragrafo fa, ed implementeremo i 5 operatori aritmetici di base.

Vediamo per prima cosa il codice XAML che disegna la nostra finestra,

 Title="Mini Calculator" Height="350" Width="525" Loaded="Window_loaded">
  • Modifichiamo l’attributo Title=”MainWindow” in Title=”Mini Calculator
  • Aggiungiamo l’attributo Loaded=”Window_Loaded” perché al caricamento della finestra scriveremo il codice che abbiamo usato per testare gli operatori nei paragrafi precedenti.
<Grid >
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
...
  • Aggiungiamo il tag Grid.RowDefinitions alla Grid, e al suo interno definiamo 4 righe che ci permetteranno di inserire i componenti per la nostra calcolatrice.
  • Spostiamoci sulla scritta Window_loaded e facciamo Tasto Destro, Go To Definition

Riporto il codice per il metodo Window_Loaded che dimostra il codice di test delle operazioni aritmetiche e visualizza i risultati dell’operazione sulla textbox result.

private void Window_loaded(object sender, RoutedEventArgs e)
{
	int integer1 = 3280;
	int integer2 = 5420;
 
	int integerResult = integer1 + integer2;
	Result.Text = "\r\n" + integer1.ToString() + " + " + integer2.ToString() + " = " + integerResult.ToString();
 
	integerResult = integer1 - integer2;
	Result.Text = Result.Text + "\r\n" + integer1.ToString() + " - " + integer2.ToString() + " = " + integerResult.ToString();
 
	integerResult = integer1 * integer2;
	Result.Text = Result.Text + "\r\n" + integer1.ToString() + " * " + integer2.ToString() + " = " + integerResult.ToString();
 
	integerResult = integer2 / integer1;
	Result.Text = Result.Text + "\r\n" + integer2.ToString() + " / " + integer1.ToString() + " = " + integerResult.ToString();
 
	integerResult = integer2 % integer1;
	Result.Text = Result.Text + "\r\n" + integer2.ToString() + " % " + integer1.ToString() + " = " + integerResult.ToString();
 
 
	ulong unsignedLong1 = 7890000000;
	ulong unsignedLong2 = 389000000000;
 
	ulong unsignedLongResult = unsignedLong1 + unsignedLong2;
	Result.Text = Result.Text + "\r\n" + unsignedLong1.ToString() + " + " + unsignedLong2.ToString() + " = " + unsignedLongResult.ToString();
 
	unsignedLongResult = unsignedLong1 - unsignedLong2;
	Result.Text = Result.Text + "\r\n" + unsignedLong1.ToString() + " - " + unsignedLong2.ToString() + " = " + unsignedLongResult.ToString();
 
	unsignedLongResult = unsignedLong1 * unsignedLong2;
	Result.Text = Result.Text + "\r\n" + unsignedLong1.ToString() + " * " + unsignedLong2.ToString() + " = " + unsignedLongResult.ToString();
 
	unsignedLongResult = unsignedLong2 / unsignedLong1;
	Result.Text = Result.Text + "\r\n" + unsignedLong2.ToString() + " / " + unsignedLong1.ToString() + " = " + unsignedLongResult.ToString();
 
	unsignedLongResult = unsignedLong2 % unsignedLong1;
	Result.Text = Result.Text + "\r\n" + unsignedLong2.ToString() + " % " + unsignedLong1.ToString() + " = " + unsignedLongResult.ToString();
 
 
 
	float floatingpoint1 = 12.789f;
	float floatingpoint2 = 7953.17f;
 
	float floatingpointResult = floatingpoint1 + floatingpoint2;
	Result.Text = Result.Text + "\r\n" + floatingpoint1.ToString() + " + " + floatingpoint2.ToString() + " = " + floatingpointResult.ToString();
 
	floatingpointResult = floatingpoint1 - floatingpoint2;
	Result.Text = Result.Text + "\r\n" + floatingpoint1.ToString() + " - " + floatingpoint2.ToString() + " = " + floatingpointResult.ToString();
 
	floatingpointResult = floatingpoint1 * floatingpoint2;
	Result.Text = Result.Text + "\r\n" + floatingpoint1.ToString() + " * " + floatingpoint2.ToString() + " = " + floatingpointResult.ToString();
 
	floatingpointResult = floatingpoint2 / floatingpoint1;
	Result.Text = Result.Text + "\r\n" + floatingpoint2.ToString() + " / " + floatingpoint1.ToString() + " = " + floatingpointResult.ToString();
 
	floatingpointResult = floatingpoint2 % floatingpoint1;
	Result.Text = Result.Text + "\r\n" + floatingpoint2.ToString() + " % " + floatingpoint1.ToString() + " = " + floatingpointResult.ToString();
 
 
 
}

L’esempio con i 3 tipi di dati di base utilizzati, l’uso dell’operatore + delle stringhe e uso del metodo ToString.

Proseguiamo a creare la mini calcolatrice:

<TextBox
    Name="LeftValue"
    Grid.Row="0"
    MinWidth="300"
    Margin="4,4,4,4"
    HorizontalAlignment="Right"
    VerticalAlignment="Center"
    Background="AliceBlue"
    FontSize="24" />
<TextBox
    Name="RightValue"
    Grid.Row="1"
    MinWidth="300"
    Margin="4,4,4,4"
    HorizontalAlignment="Right"
    VerticalAlignment="Center"
    Background="AliceBlue"
    FontSize="24" />
<TextBox
    Name="Result"
    Grid.Row="2"
    MinWidth="500"
    Margin="4,4,4,4"
    HorizontalAlignment="Left"
    VerticalAlignment="Center"
    Background="LemonChiffon"
    FontSize="24"
    Foreground="RoyalBlue"
    VerticalScrollBarVisibility="Auto" />

Sotto alla chiusura del tag Grid.RowDefinitions, Inseriamo 3 Textbox, che conterranno i 2 operandi (sinistro e destro) e il Risultato. Stavolta, per mostrare come si disegna un componente nello XAML, ho modificato le property che danno alle Textbox l’aspetto e la forma che vedremo nell’interfaccia inizializzandole da Xaml. Quindi oltre a Name, ho modificato Background che indica il colore di sfondo, Margin, che indica il margine attorno alla Textbox, MinWidth, che indica la dimensione minima in larghezza della Textbox, l’allineamento orizzontale e verticale rispetto alla casella della Grid, la Row (Riga) della Grid ove la Textbox deve essere posizionata, ricordo che partono con indice zero quindi zero è la prima riga, due è la terza. Ho anche reso più grande la font con cui sono scritti i dati.

<StackPanel
    Grid.Row="3"
    Margin="2"
    FlowDirection="RightToLeft"
    Orientation="Horizontal">
            <Button
        Margin="2"
        Padding="10,2,10,2"
        Background="Aquamarine"
        Click="Add_Click"
        ToolTip="Add">
                <TextBlock
            FontSize="24"
            FontWeight="Bold"
            Text="+" />
            </Button>
            <Button
        Margin="2"
        Padding="10,2,10,2"
        Background="Aquamarine"
        Click="Subtract_Click"
        ToolTip="Subtract">
                <TextBlock
            FontSize="24"
            FontWeight="Bold"
            Text="-" />
            </Button>
 
            <Button
        Margin="2"
        Padding="10,2,10,2"
        Background="Aquamarine"
        Click="Multiply_Click"
        ToolTip="Multiply">
                <TextBlock
            FontSize="24"
            FontWeight="Bold"
            Text="*" />
            </Button>
 
            <Button
        Margin="2"
        Padding="10,2,10,2"
        Background="Aquamarine"
        Click="Divide_Click"
        ToolTip="Divide">
                <TextBlock
            FontSize="24"
            FontWeight="Bold"
            Text="/" />
            </Button>
 
            <Button
        Margin="2"
        Padding="10,2,10,2"
        Background="Yellow"
        Click="IntDivide_Click"
        ToolTip="Integer Divide">
                <TextBlock
            FontSize="24"
            FontWeight="Bold"
            Foreground="DarkGreen"
            Text="/" />
            </Button>
            <Button
        Margin="2"
        Padding="10,2,10,2"
        Background="Yellow"
        Click="Module_Click"
        ToolTip="Module">
                <TextBlock
            FontSize="24"
            FontWeight="Bold"
            Foreground="DarkGreen"
            Text="%" />
            </Button>
 
        </StackPanel>

Il contenitore dei bottoni di comando delle operazioni e i bottoni stessi: lo StackPanel è un contenitore rettangolare in cui gli oggetti all’interno si dispongono in base a come inseriti uno dietro l’altro. In questo caso abbiamo indicato Orientation=Horizontal, quindi i bottoni si posizionano su una riga, e FlowDirection=RightToLeft che significa che i bottoni si posizioneranno da destra verso sinistra a partire dal primo.

Ognuno dei Button contiene il Text con il simbolo della operazione, il ToolTip che descrive l’operazione (apparirà quando faremo mouse over) ho cambiato i colori ai bottoni in modo da mostrare anche le divisioni intere e la funzione modulo che è stata fatta sugli interi.

L’attributo Click=”Nomemetodo” per ognuno dei bottoni, ci permetterà di scrivere il codice necessario a effettuare ognuna delle operazioni.

Facciamo Tasto Destro, Go To Definition su tutti i bottoni in modo da creare i metodi che rispondono al click dei bottoni stessi:

private void Add_Click(object sender, RoutedEventArgs e)
{
	decimal leftOperator = 0.0m;
	decimal.TryParse(LeftValue.Text, out leftOperator);
	decimal rightOperator = 0.0m;
	decimal.TryParse(RightValue.Text, out rightOperator);
	Result.Text = (leftOperator + rightOperator).ToString();
}

I metodi saranno molto simili, le 4 operazioni base sono state effettuate su variabili di tipo decimal (numero a virgola mobile a 128 bit) che sono quelle di dimensione più grande fra i numeri. Approfittiamo di questo piccolo programmino, per spiegare come, anchele classi che rappresentano i dati numerici di base, in C# forniscono dei metodi per lavorare facilmente con esse. Cosa abbiamo fatto nel codice qui sopra:

  • per prima cosa abbiamo azzerato la variabile che rappresenta l’operando di sinistra.
  • poi, abiamo chiamato il metodo della classe decimal TryParse, fornendo a tale metodo due dati, il primo è la stringa contenente il testo digitato nella TextBox LeftValue, il secondo è la variabile leftOperator che abbiamo appena definito e inizializzato.

Cosa fa il metodo TryParse? in inglese Try=provare Parse=esaminare, il metodo TryParse lo troveremo in tutte le classi numeriche che possono essere elaborate a partire da una stringa, ed anche nella classe DateTime, che rappresenta data e ora. Il suo scopo è, leggere la stringa passata come parametro e convertirla in questo caso in un valore numerico in virgola mobile. Se la stringa non fosse un numero, il valore restituito sarebbe quello da noi assegnato alla variabile, quindi, in questo caso zero.

Ripetiamo la cosa anche per l’operando di destra e poi, effettuiamo l’operazione, in questo caso la somma, e ritrasformiamo il risultato in una stringa che scriviamo sulla casella di testo Result.

private void Subtract_Click(object sender, RoutedEventArgs e)
{
	decimal leftOperator = 0.0m;
	decimal.TryParse(LeftValue.Text, out leftOperator);
	decimal rightOperator = 0.0m;
	decimal.TryParse(RightValue.Text, out rightOperator);
	Result.Text = (leftOperator - rightOperator).ToString();
 
}
 
private void Multiply_Click(object sender, RoutedEventArgs e)
{
	decimal leftOperator = 0.0m;
	decimal.TryParse(LeftValue.Text, out leftOperator);
	decimal rightOperator = 0.0m;
	decimal.TryParse(RightValue.Text, out rightOperator);
	Result.Text = (leftOperator * rightOperator).ToString();
}

Sottrazione e moltiplicazione sono praticamente identici.

private void Divide_Click(object sender, RoutedEventArgs e)
{
	decimal leftOperator = 0.0m;
	decimal.TryParse(LeftValue.Text, out leftOperator);
	decimal rightOperator = 0.0m;
	decimal.TryParse(RightValue.Text, out rightOperator);
	if (rightOperator == 0.0m)
	{
		Result.Text = "Errore, divisione x zero!";
	}
	else
	{
		Result.Text = (leftOperator / rightOperator).ToString();
	}
}

Per la divisione, invece, abbiamo aggiunto un costrutto di controllo, ovvero se il divisore (rightOperator) fosse zero, scriveremmo un messaggio di errore altrimenti eseguiamo la divisione. Ora, per i principianti, sappiamo che non abbiamo ancora spiegato i costrutti di controllo, pertanto tenete per buono sia l’if che quanto scritto fra parentesi tonde, che l’ else che viene come seconda parte del controllo.

private void Module_Click(object sender, RoutedEventArgs e)
{
	long leftOperator = 0L;
	long rightOperator = 0L;
	long.TryParse(LeftValue.Text, out leftOperator);
	long.TryParse(RightValue.Text, out rightOperator);
	if (rightOperator == 0L)
	{
		Result.Text = "Errore, divisione x zero!";
	}
	else
	{
		Result.Text = (leftOperator % rightOperator).ToString();
	}
}
 
private void IntDivide_Click(object sender, RoutedEventArgs e)
{
	long leftOperator = 0L;
	long.TryParse(LeftValue.Text, out leftOperator);
	long rightOperator = 0L;
	long.TryParse(RightValue.Text, out rightOperator);
	if (rightOperator == 0L)
	{
		Result.Text = "Errore, divisione x zero!";
	}
	else
	{
		Result.Text = (leftOperator / rightOperator).ToString	}
}

Gli ultimi 2 metodi, che riguardano la divisione intera e il resto della divisione intera, sono identici a quello precedente cambiando il tipo di dato da decimal a long, che è un intero (quindi niente virgole).

Se vi state chiedendo perché ho scritto

decimal leftOperator = 0.0m;
long leftOperator = 0L;

Perché dopo l’ uguale non ho messo semplicemente 0, in realtà avrei potuto farlo e C# probabilmente non avrebbe protestato quando compilava, ma è bene comprendere da subito alcune delle cose più “sottilmente infide” della programmazione.

in C# 0 non rappresenta semplicemente  uno zero numerico, ma rappresenta la rappresentazione intera  dello zero, ora, è permesso ad una variabile di dimensioni più ampie ospitare un valore più piccolo, quindi posso assegnare senza problemi un intero a 32 bit  ad un intero a 64 bit, il contrario invece provoca un errore e richiede un operazione di conversione, onde informare il compilatore che il programmatore sa quel che sta facendo.

Per questo motivo, è stata introdotta una notazione specifica per le costanti numeriche che ci permette di informare il sistema riguardo il tipo di numero che la costante rappresenta.

  • miaVariabile = 0; può essere applicata a variabili di tipo byte, short, int, ed anche al  Long (perché le più grandi possono ospitare un valore più piccolo)
  • miaVariabile = 0L; indica che sto inizializzando la variabile con un intero a 64 bit, se miaVariabile fosse dei 3 tipi più piccoli il compilatore mi darebbe un errore dicendo Non posso convertire un valore Long in un byte (o short o int) ti sei dimenticato una conversione?
  • miaVariabile = 0.0f indica che sto inizializzando la variabile con un numero in virgola mobile a 32 bit, pertanto qualsiasi variabile intera (indipendentemente dalla grandezza) mi darà un errore indicando che non può ospitare un numero in virgola mobile. Le variabili di tipo double e decimal invece accetteranno il numero più piccolo automaticamente facendo la conversione.
  • miaVariabile = 0.0; indica che sto inizializzando la variabile con un numero in virgola mobile a 64 bit, pertanto sia le variabili intere che la variabile float daranno errore, mentre decimal accetterà il valore convertendolo.
  • miaVariabile = 0.0m; indica che sto inizializzando la variabile con un numero in virgola mobile a 128 bit, pertanto solo il decimal permetterà il suo uso.

Pertanto il suffisso per la notazione delle variabili numeriche è: nessuno (interi fino a 32 bit) L = interi a 64 bit f = floating point a 32 bit, .n = dove n è una o più cifre decimali  floating point a 64 bit m = numero in virgola mobile a 128 bit.

Operatore + fra stringhe sommare delle stringhe

Gli operatori C# sono semplicemente delle abbreviazioni per il nome di un metodo (il metodo è una serie di istruzioni che eseguono una modifica su una classe o eseguono un operazione fornendo un risultato, in tutti i piccoli esempi di codice fino a qui scritti, abbiamo scritto dei metodi. Ora, il fatto che un operatore sia semplicemente un nome abbreviato per una serie di istruzioni ci suggerisce che: In C# possiamo creare gli operatori anche nelle classi scritte da noi. Questo è esattamente quello che è stato fatto da chi ha scritto la classe String (che è la classe assegnata come alias alla keyword string di C# dal Framework .Net).

pertanto, da qualche parte nella classe String del framework ci sarà un codice simile a questo:

public string operator +(string left, string right)
{
   ...
}	  

Che implementa la somma fra due stringhe, intesa come creazione di una nuova stringa che contiene tutti i caratteri della stringa di destra e quelli della stringa di sinistra.

Ho evidenziato la frase creazione di una nuova stringa, perché è molto importante per l’efficienza dei vostri programmi, ricordate che quando scrivete

string leftString = "Tanto tempo fa ";
string rightString = "In una galassia lontana lontana...";
string sumString = leftString + rightString;

In memoria ci saranno 3 diverse stringhe, le due originali e una terza contenente la somma delle due. Ne parleremo estesamente in una lezione dedicata alle stringhe che sono fra gli oggetti più comuni che userete nei vostri programmi futuri, vi introduco solo un ultimo concetto sulle stringhe così che ve ne ricordiate. In C# le stringhe sono immutabili, pertanto, quando create una stringa, essa non verrà mai più modificata, se modificate una stringa, in realtà quello che accadrà sarà la creazione di una nuova stringa ed il “garbaging” della stringa precedente. Ma non andiamo troppo avanti, anche la gestione della memoria ed il Garbage collector saranno qualcosa di cui parleremo in una specifica lezione futura.

Ricapitolando

  • Anche C# come ogni lingua umana ha una sua punteggiatura che permette di creare la sintassi e la grammatica comprensibile al compilatore (e quindi al computer).
  • Le operazioni aritmetiche di base possono essere effettuate in un programma C# usando gli operatori aritmetici standard più, meno, moltiplicazione, divisione, a cui si aggiunge il modulo della divisione.
  • Gli operatori aritmetici però in un linguaggio di programmazione sono in realtà delle abbreviazioni perdei metodi che sono implementati dalle classi che utilizziamo per compiere le operazioni suddette.
  • Da qui, la possibilità di implementare la somma su una classe stringa che non è un numero.

Sicuramente parleremo ancora di operatori nelle prossime lezioni. La prossima in particolare ci introdurrà gli operatori logici e l’algebra di boole.

basemath_calculator_01[10]

basemath_calculator_02[10]

basemath_calculator_03[10]

basemath_calculator_04[10]

basemath_calculator_05[10]

Alcuni esempi dei risultati, ma spero vogliate provare a giocarci un poco da soli.

Riepilogo

In questo articolo abbiamo trattato i seguenti argomenti

  • Gli operatori di C#
  • Operatori aritmetici, le 4 operazioni
  • Operatore Modulo
  • Operatori di incremento e decremento
  • Un semplice programma per usare questi operatori

Potete trovare il codice relativo all’esempio collegato a questo articolo al link seguente:

Per qualsiasi domanda, osservazione, approfondimento usate il link di contatto in cima alla pagina.