2015-10-15 14 views
16

Su una piattaforma a complemento a complemento, quale sarebbe il seguente codice stampato?In che modo std :: cout stampa zero zero in un sistema a complemento a un complemento?

#include <iostream> 

int main() { 
    int i = 1, j = -1; 

    std::cout << i+j << std::endl; 
    return 0; 
} 

ho il sospetto che sarebbe stampare "0" invece di "-0", ma io non riesco a trovare niente di autorevole.

Modifica: Per chiarire, sono interessato a come -0 verrebbe stampato, diverse persone hanno suggerito che, in pratica, l'implementazione del complimento di uno potrebbe non generare uno zero negativo con il codice precedente.

In questi casi, il seguente è stato suggerito per generare in realtà un -0:

#include <iostream> 

int main() { 
    std::cout << ~0 << std::endl; 
    return 0; 
} 

La questione rimane ancora: che cosa sarà questa stampa?

+1

Stampa '0' su [coliru] (http://coliru.stacked-crooked.com/a/ac6c491f7ca7f7a9). E sono abbastanza sicuro che è quello che dovrebbe succedere ogni volta. –

+2

Dubito che questo stamperà mai '-0' su qualsiasi sistema. – nwp

+1

Permesso di taggare anche questo C? Suppongo che i programmatori C siano più vicini a questa roba. – Bathsheba

risposta

5

Prima di tutto, solo per chiarire cosa, creare uno zero negativo utilizzando operazioni bit a bit e quindi utilizzare il valore risultante non è portabile. Detto questo, nulla specifica nella documentazione di fprintf (quindi, di std::basic_ostream::operator<<(int)) se il bit di segno nella rappresentazione di int corrisponde a un bit di riempimento nella rappresentazione di unsigned o un bit di valore effettivo.

In conclusione, si tratta di un comportamento non specificato.

#include <iostream> 

int main() { 
    std::cout << ~0 << std::endl; 
    return 0; 
} 
+2

Utilizzo di operazioni bit a bit per creare uno zero negativo intero certamente * è * portatile per altri computer a complemento d'uno. È vero, non funzionerà su un computer a due complementi, non funzionerà perché lo zero negativo non esiste nel complemento a due. – George

+2

"è certamente portatile per altri computer a complemento d'una persona:" è quello che chiamerei non portatile;). – YSC

+3

@ YSC Questa domanda si applica solo ai computer compliant, quindi, per tutti gli effetti, sono d'accordo con George. – Tyzoid

5

Aggiungendo infatti n a -ndovrebbe dare uno zero negativo. Ma la generazione di -0 non si verifica in pratica poiché l'aggiunta del complemento a 1 utilizza una tecnica chiamata che integra il sottrattore (il secondo argomento è completato e sottratto dal primo).

(Il modo idiomatico di ottenere uno zero virgola mobile con segno non si applica qui poiché non è possibile dividere un numero intero per zero).

+2

Non so molto di queste cose - ma è possibile ottenere uno zero negativo dividendo -1 per un numero positivo di magnitudo maggiore (usando la divisione di interi) ? (o in effetti positivo 1 per qualche negativo di magnitudo maggiore) – davmac

+0

Sono molto arrugginito anche su questo - non ho incasinato con il complemento 1 dai tempi della mia università - ma, per quanto ricordo, tutte le operazioni aritmetiche su 1 complemento sono implementati in modo che tu * d on't * finiscono con uno zero negativo firmato. – Bathsheba

+6

Se * conosci * hai un sistema di complemento a uno, generare zero negativo per il test è semplice: '~ 0'. E mentre è vero, è difficile ottenere uno zero negativo naturalmente su un sistema del genere, non penso sia impossibile. Questo in realtà non risponde alla domanda come chiesto. –

0

Se vediamo il punto teorico del complemento a uno. Poiché lo zero è definito come (+/-) 0 ci saranno due valori binari per 0 se abbiamo 4 valori di bit lo zero sarà 0000 (+0) e 1111 (-0). Di conseguenza, è sempre necessario eseguire una correzione se un'operazione, un'addizione o una sottrazione hanno in esso un'operazione di passaggio a zero.

Così, per esempio, se facciamo la seguente operazione -2+6=4 il risultato sarà calcolata come segue:

1101 (-2) 
+ 0110 (6) 
------ 
1100 (add carry) 
====== 
    0011 (+3) 

Come si può vedere nel funzionamento Bit il risultato non è corretto ed è solo il risultato incompleto. In questo caso dobbiamo aggiungere un +1 al valore per ottenere il risultato corretto. Per identificare se il +1 deve essere aggiunto dobbiamo dare un'occhiata al risultato di add carry. Se il numero più a sinistra 100 è UNO di quello che dobbiamo aggiungere +1 al risultato per ottenere il risultato corretto.

Se abbiamo uno sguardo al tuo esempio:

0001 (+1) 
+ 1110 (-1) 
------ 
0000 (add carry) 
====== 
    1111 (-0) 

Vediamo che il risultato sarà -0 e questo sarà il risultato finale perché la sinistra aggiungere bit di riporto è 0.

+0

Mentre corretto, ho familiarità con la meccanica dell'addizione compl. (In effetti, questo è il motivo per cui ho citato '(-0) = (-1) + 1' nel mio post originale). La mia domanda è che cosa produrrà nello standard C++/una macchina di complimenti. – Tyzoid

5

Guardando attraverso il codice sorgente di glibc, ho trovato queste righe in vfprintf.c:

532  is_negative = signed_number < 0;     \ 
533  number.word = is_negative ? (- signed_number) : signed_number;  \ 
534           \ 
535  goto LABEL (number);       \ 
... 
683  if (is_negative)       \ 
684   outchar (L_('-'));       \ 

Quindi sembrerebbe che la condizione è signed_number < 0, che return false per un -0.

come @Ysc menzionato, nulla nella documentazione fornisce alcuna specifica per la stampa -0, quindi un'implementazione diversa della piattaforma libc (su una piattaforma compliant) potrebbe produrre un risultato diverso.