Forced sales - Ultima task errata

Nel problema forced sales, per trovare l’area utilizzo la formula generale per i poligoni irregolari.

image

Non capisco se il fatto che l’ultima task sia errata è dovuto da dei valori troppo alti, che mi danno in output 123456x10^23 o se c’è un errore di fondo nell’impostazione.

code->#include <iostream>using namespace std;int main(){ long int num; - Pastebin.com

Problema risolto.

Moltiplicare per 0.5 è diverso da dividere per due.

Perchè?

Da un punto di vista matematico, preso un numero intero n, la scrittura n \div 2 equivale a n \times 0.5. Tuttavia, in C++ (come in numerosi altri linguaggi di programmazione) le due scritture non sono necessariamente equivalenti, da un punto di vista di codice compilato – ovvero quello che viene eseguito dal computer.

Leggendo il codice di esempio, troviamo che la riga interessata dal bug è

long long int res = abs(a) * 0.5;

e analizzando ulteriormente il codice possiamo trovare la definizione della variabile a come

long long int a = 0;

Avendo questi dati, possiamo semplificare l’operazione, riassumendola come: long long int * 0.5. In breve, stiamo moltiplicando un long long per un float. Per questo motivo, il compiler ha bisogno di fare un casting da long long a un numero a virgola mobile.

Nell’operazione long long int / 2, invece, stiamo dividendo un long long int per un int. In C++, la divisione tra due interi è possibile senza effettuare casting di alcun tipo – l’operatore / è infatti associato all’operazione di divisione intera quando si lavora con due interi.

Operando con numeri molto grandi, è possibile che alcuni risultati non coincidano. Basta provare, anche su un IDE online, a lavorare su numeri come 2^{61} (il numero usato nell’esempio qui sotto).

Programma di esempio
#include <iostream>

using namespace std;

long long int moltiplicazione(long long int num)
{
    long long int res = num * 0.5;
    return res;
}

long long int divisione(long long int num)
{
    long long int res = num / 2;
    return res;
}

int main()
{
    cout << "      n * 0.5      |       n / 2       \n-------------------|-------------------\n";

    long long int n = 1LL << 62LL; // numero pari molto grande
    cout << moltiplicazione(n) << '|' << divisione(n) << '\n';

    n = n - 1; // numero molto grande ma dispari
    cout << moltiplicazione(n) << '|' << divisione(n) << '\n';
    return 0;
}

È possibile vedere le differenze tra le due funzioni in un explorer di codice compilato, come GodBolt – puoi vedere qui la differenza tra le due funzioni usate.

Spero di aver chiarito il tuo dubbio, se hai altre domande sentiti libero di chiedere chiarimenti, anche se è meglio aprire un nuovo thread – questo è stato chiuso 4 anni fa! – in modo da avere più visibilità.

Buona giornata! :slight_smile:

Ok perfetto, grazie mille, mi hai chiarito tutti i dubbi. Gentilissimo.