Domanda

long long int A = 3289168178315264;
long long int B = 1470960727228416;
double D = sqrt(5);

long long int out = A + B*D;

printf("%lld",out);

Questo dà il risultato: -2147483648

Non riesco a capire perché (dovrebbe essere un risultato positivo). Qualcuno può aiutare?

È stato utile?

Soluzione

La mia ipotesi è che il compilatore debba arrotondare il risultato da " A + B * D " prima in un numero intero, perché stai memorizzando il risultato all'interno di un campo int. Quindi, sostanzialmente, stai riscontrando un conflitto di tipo di dati.

Sia A che B sono ancora numeri validi per un int long long, che è lungo 8 byte. Potresti anche moltiplicarli per 1.000 e avere ancora valori int long long validi. In alcune altre lingue è anche noto come int64.

Un doppio, tuttavia, è anche a 64 bit, ma parte di questi sono usati come esponente. Quando moltiplichi un doppio con un int64, il risultato sarebbe un altro doppio. L'aggiunta di un altro int64 lo mantiene ancora un doppio. Quindi stai assegnando nuovamente il risultato a un int64 senza utilizzare un metodo di arrotondamento specifico. Non mi sorprenderebbe se il compilatore usasse una funzione di arrotondamento a 4 bit per questo. Sono anche sorpreso che il compilatore non vomiti e non si rompa su quell'affermazione!

In ogni caso, quando si usano numeri grandi come questi, è necessario prestare particolare attenzione quando si mescolano tipi diversi.

Altri suggerimenti

forse devi specificare quelle costanti come " long long " letterali? per esempio. 3289168178315264LL

Quale compilatore / sistema operativo stai usando? Ho eseguito il tuo codice utilizzando Visual C ++ 2008 Express Edition su Windows XP e IT WORKS - risposta: 6578336356630528 (questo è un numero a 53 bit, quindi si inserisce semplicemente in un doppio).

Ho anche provato due varianti per vedere se l'ordine delle operazioni contava:

long long int out = A; out + = B * D;

long long int out = B * D; out + = A;

Anche entrambi funzionano!

Curioso.

La tua risposta (devi verificare) viene calcolata correttamente, tuttavia, provoca un overflow nel bit del segno, il che rende la risposta negativa. Soluzione: rendere tutte le variabili non firmate.

Perché:

I numeri sono memorizzati come serie di bit nella memoria del tuo computer. Il primo bit di una tale serie, quando impostato, indica che il numero è negativo. Quindi il calcolo funziona, ma trabocca nel bit del segno.

Raccomandazione:

Se lavori con numeri così grandi, ti consiglio di ottenere una libreria aritmetica multiprecisione. Ti farò risparmiare un sacco di tempo e problemi.

Il parametro per sqrt dovrebbe essere doppio .

#include <math.h>
double sqrt( double num );

E dovremmo anche esplicitare il cast del risultato da B * D a long long.

    long long int A = 3289168178315264;
    long long int B = 1470960727228416;
    double D = sqrt(5.0);
    printf("%f\n",D);
    long long int out = A + (long long) (B * D);
    printf("%lld",out);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top