Torna indietro   Hardware Upgrade Forum > Software > Programmazione

FUJIFILM X-T30 III, la nuova mirrorless compatta
FUJIFILM X-T30 III, la nuova mirrorless compatta
FUJIFILM X-T30 III è la nuvoa fotocamera mirrorless pensata per chi si avvicina alla fotografia e ricerca una soluzione leggera e compatta, da avere sempre a disposizione ma che non porti a rinunce quanto a controllo dell'immagine.
Oracle AI World 2025: l'IA cambia tutto, a partire dai dati
Oracle AI World 2025: l'IA cambia tutto, a partire dai dati
Da Las Vegas, la visione di Larry Ellison e la concretezza di Clay Magouyrk definiscono la nuova traiettoria di Oracle: portare l’intelligenza artificiale ai dati, non i dati all’intelligenza, costruendo un’infrastruttura cloud e applicativa in cui gli agenti IA diventano parte integrante dei processi aziendali, fino al cuore delle imprese europee
Micron e millisecondi: la piattaforma ServiceNow guida l'infrastruttura IT di Aston Martin F1
Micron e millisecondi: la piattaforma ServiceNow guida l'infrastruttura IT di Aston Martin F1
Dalla precisione estrema dei componenti alla gestione digitale dei processi: come la piattaforma ServiceNow consente ad Aston Martin Aramco Formula One Team di ottimizzare risorse IT e flussi operativi in un ambiente dove ogni millesimo di secondo conta
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 10-04-2007, 11:09   #1
kappa85
Senior Member
 
L'Avatar di kappa85
 
Iscritto dal: Feb 2004
Messaggi: 3797
scambiare due valori

Un mio prof. ha affermato che è possibile scambiare i valori di due variabili (per esempio intere) senza usare variabili di appoggio nè altro spazio aggiuntivo, utilizzando solo 2 istruzioni... come si fa?
kappa85 è offline   Rispondi citando il messaggio o parte di esso
Old 10-04-2007, 11:36   #2
andbin
Senior Member
 
L'Avatar di andbin
 
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
Quote:
Originariamente inviato da kappa85 Guarda i messaggi
Un mio prof. ha affermato che è possibile scambiare i valori di due variabili (per esempio intere) senza usare variabili di appoggio nè altro spazio aggiuntivo, utilizzando solo 2 istruzioni... come si fa?
Bastano 3 xor, anche in 1 istruzione unica:
Codice:
#include <stdio.h>

int main (void)
{
    int a=2, b=5;

    printf ("%d %d\n", a, b);

    a ^= b ^= a ^= b;

    printf ("%d %d\n", a, b);

    return 0;
}
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%)
andbin è offline   Rispondi citando il messaggio o parte di esso
Old 10-04-2007, 13:04   #3
kappa85
Senior Member
 
L'Avatar di kappa85
 
Iscritto dal: Feb 2004
Messaggi: 3797
Quote:
Originariamente inviato da Antonio23 Guarda i messaggi
bellissimo! ma perchè funziona? non è che lo puoi spiegare....??
quoto.. e a livello di costi di esecuzione è più pesante di un normale scambio con un variabile temp?
kappa85 è offline   Rispondi citando il messaggio o parte di esso
Old 10-04-2007, 14:21   #4
pisto
 
Messaggi: n/a
l'idea è la stessa del RAID (almeno per quel che ne so di come funziona il raid), solo che il disco con lo xor degli altri è proprio un disco di dati stesso
  Rispondi citando il messaggio o parte di esso
Old 10-04-2007, 14:22   #5
andbin
Senior Member
 
L'Avatar di andbin
 
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
Certo che posso spiegarlo. Si basa sull'utilizzo di una exclusive-or (XOR), che ha una proprietà particolare: è, per così dire "reversibile". Dato un valore A, se faccio lo xor con B, ottengo C e se a questo riapplico lo xor con B, riottengo A. In pratica: (A xor B) xor B = A

Per fare lo scambio tra 2 valori, la procedura per esteso è:
A = A xor B
B = A xor B
A = A xor B

Es. A=1 (0001 in binario) e B=8 (1000 in binario)

1) A=9 perché 0001 xor 1000 dà 1001
2) B=1 perché 1001 xor 1000 dà 0001
3) A=8 perché 1001 xor 0001 dà 1000

In C (e altri linguaggi) a = a^b si può scrivere a ^= b, ed essendo le assegnazioni associative da destra a sinistra, scrivere a ^= b ^= a ^= b è solo un modo più "figo" per realizzare la procedura sopra.

Dal punto di vista delle prestazioni, bisogna vedere se il compilatore è furbo o meno. Scambiare 2 valori usando un temporaneo richiede tecnicamente 3 assegnazioni, mentre con lo xor richiede 3 assegnazioni con xor.

Prendiamo questo sorgente:
Codice:
#include <stdio.h>

int main (void)
{
    int a, b, t;

    scanf ("%d %d", &a, &b);

    printf ("%d %d\n", a, b);

    a ^= b ^= a ^= b;

    printf ("%d %d\n", a, b);

    t = a;
    a = b;
    b = t;

    printf ("%d %d\n", a, b);

    return 0;
}
Compilato con gcc su Linux attivando le ottimizzazioni, ottengo:
Codice:
0x8048370 <main>:       push   %ebp
0x8048371 <main+1>:     mov    %esp,%ebp
0x8048373 <main+3>:     sub    $0x8,%esp
0x8048376 <main+6>:     and    $0xfffffff0,%esp
0x8048379 <main+9>:     push   %ecx
0x804837a <main+10>:    lea    0xfffffffc(%ebp),%ecx
0x804837d <main+13>:    push   %ecx
0x804837e <main+14>:    lea    0xfffffff8(%ebp),%edx
0x8048381 <main+17>:    push   %edx
0x8048382 <main+18>:    push   $0x80484b4
0x8048387 <main+23>:    call   0x804827c <scanf>
0x804838c <main+28>:    add    $0xc,%esp
0x804838f <main+31>:    mov    0xfffffffc(%ebp),%eax
0x8048392 <main+34>:    push   %eax
0x8048393 <main+35>:    mov    0xfffffff8(%ebp),%ecx
0x8048396 <main+38>:    push   %ecx
0x8048397 <main+39>:    push   $0x80484ba
0x804839c <main+44>:    call   0x804829c <printf>
0x80483a1 <main+49>:    mov    0xfffffffc(%ebp),%edx
0x80483a4 <main+52>:    mov    0xfffffff8(%ebp),%ecx
0x80483a7 <main+55>:    xor    %edx,%ecx
0x80483a9 <main+57>:    xor    %ecx,%edx
0x80483ab <main+59>:    add    $0xc,%esp
0x80483ae <main+62>:    xor    %edx,%ecx
0x80483b0 <main+64>:    push   %edx
0x80483b1 <main+65>:    push   %ecx
0x80483b2 <main+66>:    push   $0x80484ba
0x80483b7 <main+71>:    mov    %edx,0xfffffffc(%ebp)
0x80483ba <main+74>:    mov    %ecx,0xfffffff8(%ebp)
0x80483bd <main+77>:    call   0x804829c <printf>
0x80483c2 <main+82>:    mov    0xfffffff8(%ebp),%edx
0x80483c5 <main+85>:    add    $0xc,%esp
0x80483c8 <main+88>:    mov    0xfffffffc(%ebp),%ecx
0x80483cb <main+91>:    push   %edx
0x80483cc <main+92>:    push   %ecx
0x80483cd <main+93>:    push   $0x80484ba
0x80483d2 <main+98>:    mov    %ecx,0xfffffff8(%ebp)
0x80483d5 <main+101>:   mov    %edx,0xfffffffc(%ebp)
0x80483d8 <main+104>:   call   0x804829c <printf>
0x80483dd <main+109>:   xor    %eax,%eax
0x80483df <main+111>:   leave
0x80483e0 <main+112>:   ret
Nel caso di xor, il compilatore, da bravo, ha emesso le 3 xor ma nel caso di utilizzo di un temporaneo, è stato abbastanza furbo da capire che si trattava di uno swap e quindi ha semplicemente fatto 2 mov per mettere nei 2 registri le variabili "al contrario".

Bisogna comunque valutare architettura per architettura. La tecnica del XOR è sicuramente valida ad esempio su microcontrollori in cui magari non si vuole usare un temporaneo e magari, fortunatamente, una XOR ha lo stesso costo di una MOV.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%)
andbin è offline   Rispondi citando il messaggio o parte di esso
Old 10-04-2007, 14:50   #6
Marco Giunio Silano
Senior Member
 
L'Avatar di Marco Giunio Silano
 
Iscritto dal: Jun 2006
Città: Inverno: Novgorod. Estate: Haifa
Messaggi: 879
Quote:
Originariamente inviato da andbin Guarda i messaggi
Certo che posso spiegarlo. Si basa sull'utilizzo di una exclusive-or (XOR), che ha una proprietà particolare: è, per così dire "reversibile". Dato un valore A, se faccio lo xor con B, ottengo C e se a questo riapplico lo xor con B, riottengo A. In pratica: (A xor B) xor B = A

Per fare lo scambio tra 2 valori, la procedura per esteso è:
A = A xor B
B = A xor B
A = A xor B

Es. A=1 (0001 in binario) e B=8 (1000 in binario)

1) A=9 perché 0001 xor 1000 dà 1001
2) B=1 perché 1001 xor 1000 dà 0001
3) A=8 perché 1001 xor 0001 dà 1000

In C (e altri linguaggi) a = a^b si può scrivere a ^= b, ed essendo le assegnazioni associative da destra a sinistra, scrivere a ^= b ^= a ^= b è solo un modo più "figo" per realizzare la procedura sopra.

Dal punto di vista delle prestazioni, bisogna vedere se il compilatore è furbo o meno. Scambiare 2 valori usando un temporaneo richiede tecnicamente 3 assegnazioni, mentre con lo xor richiede 3 assegnazioni con xor.

Prendiamo questo sorgente:
Codice:
#include <stdio.h>

int main (void)
{
    int a, b, t;

    scanf ("%d %d", &a, &b);

    printf ("%d %d\n", a, b);

    a ^= b ^= a ^= b;

    printf ("%d %d\n", a, b);

    t = a;
    a = b;
    b = t;

    printf ("%d %d\n", a, b);

    return 0;
}
Compilato con gcc su Linux attivando le ottimizzazioni, ottengo:
Codice:
0x8048370 <main>:       push   %ebp
0x8048371 <main+1>:     mov    %esp,%ebp
0x8048373 <main+3>:     sub    $0x8,%esp
0x8048376 <main+6>:     and    $0xfffffff0,%esp
0x8048379 <main+9>:     push   %ecx
0x804837a <main+10>:    lea    0xfffffffc(%ebp),%ecx
0x804837d <main+13>:    push   %ecx
0x804837e <main+14>:    lea    0xfffffff8(%ebp),%edx
0x8048381 <main+17>:    push   %edx
0x8048382 <main+18>:    push   $0x80484b4
0x8048387 <main+23>:    call   0x804827c <scanf>
0x804838c <main+28>:    add    $0xc,%esp
0x804838f <main+31>:    mov    0xfffffffc(%ebp),%eax
0x8048392 <main+34>:    push   %eax
0x8048393 <main+35>:    mov    0xfffffff8(%ebp),%ecx
0x8048396 <main+38>:    push   %ecx
0x8048397 <main+39>:    push   $0x80484ba
0x804839c <main+44>:    call   0x804829c <printf>
0x80483a1 <main+49>:    mov    0xfffffffc(%ebp),%edx
0x80483a4 <main+52>:    mov    0xfffffff8(%ebp),%ecx
0x80483a7 <main+55>:    xor    %edx,%ecx
0x80483a9 <main+57>:    xor    %ecx,%edx
0x80483ab <main+59>:    add    $0xc,%esp
0x80483ae <main+62>:    xor    %edx,%ecx
0x80483b0 <main+64>:    push   %edx
0x80483b1 <main+65>:    push   %ecx
0x80483b2 <main+66>:    push   $0x80484ba
0x80483b7 <main+71>:    mov    %edx,0xfffffffc(%ebp)
0x80483ba <main+74>:    mov    %ecx,0xfffffff8(%ebp)
0x80483bd <main+77>:    call   0x804829c <printf>
0x80483c2 <main+82>:    mov    0xfffffff8(%ebp),%edx
0x80483c5 <main+85>:    add    $0xc,%esp
0x80483c8 <main+88>:    mov    0xfffffffc(%ebp),%ecx
0x80483cb <main+91>:    push   %edx
0x80483cc <main+92>:    push   %ecx
0x80483cd <main+93>:    push   $0x80484ba
0x80483d2 <main+98>:    mov    %ecx,0xfffffff8(%ebp)
0x80483d5 <main+101>:   mov    %edx,0xfffffffc(%ebp)
0x80483d8 <main+104>:   call   0x804829c <printf>
0x80483dd <main+109>:   xor    %eax,%eax
0x80483df <main+111>:   leave
0x80483e0 <main+112>:   ret
Nel caso di xor, il compilatore, da bravo, ha emesso le 3 xor ma nel caso di utilizzo di un temporaneo, è stato abbastanza furbo da capire che si trattava di uno swap e quindi ha semplicemente fatto 2 mov per mettere nei 2 registri le variabili "al contrario".

Bisogna comunque valutare architettura per architettura. La tecnica del XOR è sicuramente valida ad esempio su microcontrollori in cui magari non si vuole usare un temporaneo e magari, fortunatamente, una XOR ha lo stesso costo di una MOV.
__________________
Hosti non solum dandam esse viam ad fugiendum, sed etiam muniendam / Ceterum censeo Carthaginem esse delendam / Et facere et pati fortia romanum est / Nemo Romanorum pacis mentionem habere dignatus est / Roma locuta, causa finita
Milla
Marco Giunio Silano è offline   Rispondi citando il messaggio o parte di esso
Old 10-04-2007, 15:22   #7
sirus
Senior Member
 
Iscritto dal: Mar 2004
Messaggi: 16053
Sono commosso...
sirus è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


FUJIFILM X-T30 III, la nuova mirrorless compatta FUJIFILM X-T30 III, la nuova mirrorless compatta
Oracle AI World 2025: l'IA cambia tutto, a partire dai dati Oracle AI World 2025: l'IA cambia tutto, a parti...
Micron e millisecondi: la piattaforma ServiceNow guida l'infrastruttura IT di Aston Martin F1 Micron e millisecondi: la piattaforma ServiceNow...
ASUS GeForce RTX 5080 Noctua OC Edition: una custom fenomenale, ma anche enorme ASUS GeForce RTX 5080 Noctua OC Edition: una cus...
Dreame Aqua10 Ultra Roller, la pulizia di casa con un rullo Dreame Aqua10 Ultra Roller, la pulizia di casa c...
iPhone 18: Apple punta alla connessione ...
Tesla sotto indagine per la modalit&agra...
EOLO attiva la rete FWA 5G fino a 1 Gbps...
Nasce GOG Patrons: donazioni volontarie ...
Scope elettriche ai minimi: con doppio ...
Galaxy S25 Edge 5G a 639€ su Amazon: tit...
MacBook Pro M5: il teardown rivela picco...
Samsung Odyssey G30D oggi costa 87,5€, v...
4 smartphone 8/256GB a basso prezzo: rea...
Von der Leyen spiega RESourceEU: l'Europ...
YouTube, smantellata la "Ghost Netw...
Ferrari F76: la prima hypercar NFT segna...
Am9080, sono passati 50 anni dal primo p...
Inquinamento record a Nuova Delhi: il go...
Il Giappone e il 'fetish' per i dischi o...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 11:17.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Served by www3v