Ecco quello che ho fatto:
#include <stdio.h>
#include <limits.h>
int ThreeFourths(int x)
{
int x3 = x + x + x;
return (x3 >= 0) ? (x3 >> 2) : -(int)((UINT_MAX - x3 + 1) >> 2);
}
int testData[] =
{
0,
1,
-1,
2,
-2,
3,
-3,
4,
-4,
5,
-5,
-9,
11,
INT_MAX/2 + 1,
INT_MIN
};
int main(void)
{
int i;
for (i = 0; i < sizeof(testData)/sizeof(testData[0]); i++)
{
printf(" %d * 3/4 = %d\n",
testData[i], testData[i] * 3/4);
printf("ThreeFourths(%d) = %d\n",
testData[i], ThreeFourths(testData[i]));
}
return 0;
}
uscita:
0 * 3/4 = 0
ThreeFourths(0) = 0
1 * 3/4 = 0
ThreeFourths(1) = 0
-1 * 3/4 = 0
ThreeFourths(-1) = 0
2 * 3/4 = 1
ThreeFourths(2) = 1
-2 * 3/4 = -1
ThreeFourths(-2) = -1
3 * 3/4 = 2
ThreeFourths(3) = 2
-3 * 3/4 = -2
ThreeFourths(-3) = -2
4 * 3/4 = 3
ThreeFourths(4) = 3
-4 * 3/4 = -3
ThreeFourths(-4) = -3
5 * 3/4 = 3
ThreeFourths(5) = 3
-5 * 3/4 = -3
ThreeFourths(-5) = -3
-9 * 3/4 = -6
ThreeFourths(-9) = -6
11 * 3/4 = 8
ThreeFourths(11) = 8
1073741824 * 3/4 = -268435456
ThreeFourths(1073741824) = -268435456
-2147483648 * 3/4 = -536870912
ThreeFourths(-2147483648) = -536870912
Il motivo per cui non ha usato i turni giusti sugli interi negativi è semplice. Il risultato di questi spostamenti è definito dall'implementazione (secondo lo standard C) e non è garantito che sia lo stesso di un passaggio a destra con estensione di segno che potremmo aspettarci perché è l'implementazione più comune.
ho scritto (UINT_MAX - x3 + 1)
invece di limitarsi a -x3
perché può causare un overflow firmato (quando = INT_MIN
che è una potenza meno di 2), che ha undefined comportamento (per lo standard C, ancora una volta). E anche se questo comportamento indefinito è noto per essere innocuo, la semplice negazione potrebbe ancora non riuscire a produrre un numero positivo (a causa dell'asimmetria nella rappresentazione del complemento a 2 degli interi con segno).
x + x + x
può ancora produrre overflow con segno proprio come x * 3
can. Quindi, questo è lo stesso comportamento indefinito.
Btw, dal momento che gli overflow firmati risultano in UB, non dovrebbe nemmeno essere richiesto legalmente da te per raggiungerli, per non parlare delle aspettative specifiche sui risultati quando UB si verifica.
Hm ... Ho eseguito un test con questo codice nel mio pc e devo dire che sembra funzionare per i casi di test e gli esempi che hai dato Qui. Ho anche ottenuto il risultato corretto per 2147483647 – Lefteris
Quale compilatore stai usando? –
Hai scomposto per vedere tutti i valori intermedi? – EboMike