Newsgroup: it.comp.lang.c++
Titolo: valore assoluto di un int

Scusate la domanda, magari per molti banale:
qual'e' il sistema piu' veloce di togliere il segno
ad un intero. L'equivalente della funzione abs()
per i numeri a virgola mobile.
Ad esempio:
-9 diventa 9,
5 resta 5 ecc...
ciao e buone feste.

Ciao. Non so quanto performante sia, ma mi ero scritto il seguente
breve programmino di prova molto tempo fa:
#include <iostream>
int func_abs(int i)
{
	if (i >= 0)
		return i;
	else
		return i * -1;
}
int main()
{
	int val;
	std::cout << "Inserire un valore: " << std::endl;
	std::cin >> val;
	std::cout << "Il valore assoluto di " << val << " è " <<
func_abs(val) << std::endl;
	return 0;
}

breve programmino di prova molto tempo fa:
[...]
Quindi e' come pensavo: non c'e' nessun trucco che permetta
di fare questa operazione senza "if" oppure operatore "?".
ciao

 di fare questa operazione senza "if" oppure operatore "?".
Se intendevi questo  si può fare anche con un case, while, goto...
Comunque penso che devi avere un riferimento per il valore negativo
( in questo caso lo zero ).
Inoltre credo si possa rendere la funzione inline se ti serve una
piccola ottimizzazione.
Per il momento di più non so, dato che sto ancora studiando il c++.
Eventualmente attendi le risposte di qualcuno più esperto.
Ciao.

Toretto ha scritto:

Veramente, la funzione "abs" e' sempre stata in linguaggio C quella che 
operava sugli interi. Per i numeri a virgola mobile c'era la "fabs".
In C++, la funzione "abs" viene fornita in vari overload, che operano 
sia con gli interi che con i numeri a virgola mobile. Pertanto, non ha 
piu' senso usare la "fabs". Per ulteriori informazioni, leggi la 
documentazione della libreria standard.
In realta' queste funzioni non tolgono il segno a un valore, ma 
calcolano un altro valore.
Per togliere il segno a una variabile "a", usa l'istruzione:
a = abs(a);
-- 
     Carlo Milanesi
 
http://digilander.libero.it/carlmila

 return i * -1;
Equivalente a
return -i;
EMG
--
EMAG Software Homepage:     
http://www.emagsoftware.it
The EMG's ZX-Spectrum Page: 
http://www.emagsoftware.it/spectrum
The Best of Spectrum Games: 
http://www.emagsoftware.it/tbosg
The EMG Music page:         
http://www.emagsoftware.it/emgmusic
 

 B = static_cast <unsigned short> (A) & Mask;
Non funziona, per il semplice motivo che normalmente (direi sempre, ma 
non si sa mai) la codifica binaria dei numeri interi (sia in complemento 
a uno che in complemento a due) non e' tale che un numero e il suo 
opposto differiscono solo di un bit; in altre parole, a differenza dei 
numeri a virgola mobile, per gli interi non si applica semplicemente un 
bit del segno. E' vero che il bit piu' significativo rappresenta il 
segno, ma non basta invertirlo per ottenere l'opposto del numero.
Per ulteriori informazioni vedi:
http://it.wikipedia.org/wiki/Complemento_a_due


 (conoscendo l'ampiezza in bit del dato ... costrutto non portabile)
Gli interi sono praticamente sempre espressi in complemento a due.
Quindi questo ragionamento è completamente sbagliato.

 
http://it.wikipedia.org/wiki/Complemento_a_due
si giusto giusto. Ho toppato assai.
ciao
Soviet

 ha scritto nel messaggio news:47742c83$0$16020$5fc...@news.tiscali.it...

a questo punto, preferisco usare (per questioni di velocita'):
 int a;
 a=(a<0?-a:a);
-------------------------
oppure
#define INTABS(x) ((x)<0?-(x):(x))
int b;
b=INTABS(b);
che evita una chiamata a funzione non necessaria.
ciao e grazie.

 che evita una chiamata a funzione non necessaria.
Ma che stai a dire? Guarda il compilatore ci sta li mica a far nulla!
*Prima* *dimostra* che la macro offre performance maggiori, *poi* pensa
di usarla.
Ma ti anticipo: le funzioni come abs sono un esempio tipico e banale di
ottimizzazione piuttosto spinta: in particolare č facile che al posto di
quella abs venga ficcato il codice asm piů adatto per fare quello che
deve (il che potrebbe pure essere piů veloce di quello che avulsamente
dal contesto il compilatore genera per l'espressione condizionale).
Anche se non fosse cosě, una funzione piccola, con le oppurtune opzioni
di compilazione viene precisamente espansa in linea (ovvero la chiamata
di funzione non ha luogo). 
I programmatori sono *notoriamente* abilissimi ad ottimizzare pezzi di
codice dove l'ottimizzazione non serve e spesso con ottimizzazioni che
peggiorano le faccende: viceversa non ottimizzano i pezzi critici su cui
il compilatore non sa che pesci pigliare (per non parlare poi del fatto
che si divertono molto con le micro-ottimizzazioni e non ottimizzano
*globalmente* e algoritmicamente). La soluzione? Scrivere codice in modo
naturale, vedere se le performance sono accettabili, profilare,
ottimizzare dove serve.
-- 
blog:  
http://www.akropolix.net/rik0/blogs
 | Uccidete i filosofi,
site:  
http://www.akropolix.net/rik0/
      | tenetevi riso e
forum: 
http://www.akropolix.net/forum/
     | bacchette per voi.

 di usarla.
[...]
Dunque, ho fatto un programmino di test, comparando le prestazioni
della macro rispetto alla funzione presente nella libreria.
Ho usato VC++6 con "optimize max speed" attivata.
Il tempo che ho ottenuto e' stato lo stesso (differente solo per pochi
millesimi) in tutte le prove che ho effettuato.
ciao.

 millesimi) in tutte le prove che ho effettuato.
Bene. BTW, ribadisco, in C++ è bene usare le macro quanto meno
possibile.


 ad un intero.
Usa
int abs(int x);
della libreria standard (per i numeri in virgola mobile c'è fabs).
Usare le funzioni standard è quasi sempre il modo migliore di 
ottimizzare il codice.

 possibile.
E' vero sia in C++ che in C.
L'ultima che ho trovato era su buildroot, un sistema di
cross-compilazione basato sulle librerie C uclibc. Praticamente per
compatibilità con certe vecchie funzioni della stdc, venivano definite
delle "funzioni" macro denominate "index" (per compatibilità con le
vecchie funzioni index() del C). Provate ad indovinare che succede
compilando le librerie QTopiaCore con le classi che definiscono dei
metodi chiamati proprio "index"...
Le macro in C++ potrebbero, per quanto mi riguarda, essere abolite
tout-court.

 tout-court.
Assolutamente no: se impari ad usare la libreria boost::preprocessor
scopri quanto codice ripetitivo puoi fare generare al preprocessore al
posto tuo. Non sono chiaramente macro come funzioni, sono 'meta-macro'.
Tuttavia se seghi il concetto di macro seghi pure tutto questo, che č un
peccato.
E' mia abitudine fare fare il lavoro ripetitivo alla macchina invece che
digitarlo (e mantenerlo) io. :)
Ma anche al di la di questo, le macro, ben usate, possono semplicemente
rendere il codice piů leggibile. Potrei anche fartii qualche esempio,
volendo (sto pensando alla scrittura di foreign library per swipl -- che
sto facendo -- o per altri linguaggi, per dire).


 boost::preprocessor
boost/preprocessor


 posto tuo.
Devo dire che mi è capitato più di una volta di generare codice c++ a 
partire da script in python fatto apposta. Più potente di una macro.
-- 
Un libro da pausa caffè: 
http://research.microsoft.com/~daniel/uhh-download.html

 partire da script in python fatto apposta. Piů potente di una macro.
Vero, anche questo č fattibile. Tuttavia č leggermente piů noiosa da
mettere su l'infrastruttura.
Inoltre sono un fissato, prima mi dovrei scrivere una piccola libreria
per manipolare ast C++, creare quelli via programma e poi farmeli
salvare.


 digitarlo (e mantenerlo) io. :)
Perché non fare un preprocessing a parte? come, appunto, la generazione
del codice da python...

 del codice da python...
Non mi garba. Se mi metto a lavorare in Python finisce che faccio i
lavori direttamente in Python riscrivendo in C o C++ le parti più
bisognosedi performance. 
Poi ribadisco, C++ ce la fa anche da solo; tipicamente usandone features
avanzate. E' un approccio con vantaggi e svantaggi (tipo che i colleghi
devono pure essere skillati -- ma anche complicare il build system può
avere problemi --). 


 avere problemi --). 
Un buon makefile non ha problemi di alcun tipo. Puoi compilare tutto un
sistema operativo in questo senso ( buildroot e alcuni progetti di ALFS
sono un esempio).

di certe aziende anche prestigiose...
E' una brutta piaga, ahimè. Io, in un'azienda (più o meno)
prestigiosa, ci sto lavorando come consulente esterno e il codice che
ho incontrato fa mettere le mani nei capelli. E non parlo di
programmatori propriamente "inesperti", purtroppo...

 programmatori propriamente "inesperti", purtroppo...
Guarda... non ti dico cosa mi stanno costringendo a scrivere perchè
siamo in pubblico e non mi va di dire certe cose.
-- 
cc = callcc {|cc| cc.call cc}; cc.call cc

 sono un esempio).
Il build system *è* più complicato se deve anche generare dei sorgenti.
Tra l'altro è per certi versi anche sgradevole (pensa a tutta
l'attenzione che viene posta dagli autotools sul limitare i file .in,
etc etc etc).
Poi chiaro posso fare quello che voglio sul build system, eh. E tutto
IMHO.


 sia la stessa).
Ma supponendo di avere i moduli a disposizione, distinguere tra
identita' e stato condiviso non e' una complicazione gratuita?
Ciao,
Nicola

 identita' e stato condiviso non e' una complicazione gratuita?
Ovviamente si. Quello che interessa è lo stato condiviso, l'identità
condivisa è solo una condizione sufficiente per lo stato condiviso. 
Quello che volevo dire è che in alcuni casi il modo più rapido per avere
lo stato condiviso è l'identità condivisa  (vedi i moduli). 


 complicazione inutile per nulla.
Il punto che volevo enfatizzare e' che nei linguaggi dotati di moduli
il Singleton serve persino di meno che in C++, dove gia' ha raramente
ragione d'essere.
A meno di non avere un'esagerata fissazione con l'Object Orientation,
ovviamente. Tra parentesi, confondere i moduli con le classi *non* e'
una buona soluzione ;-)
Ciao,
Nicola

In altri linguaggi di livello simile al C idem: i puntatori non ci sono.
Non vorrei che leggendo queste righe si fraintendesse: il Pascal *ha*
i puntatori. Non supporta l'aritmetica tra puntatori.

 i puntatori. Non supporta l'aritmetica tra puntatori.
Si, hai ragione. La giustapposizione dei due paragrafi rende il
significato poco chiaro. Il pascal ha i puntatori senza aritmetica.
Pensavo ad altro. Per esempio, il fortran ha avuto i puntatori nella
revisione 90 (il che vuole dire che per buona parte della sua storia non
li ha avuti). Direi anche che buona parte dei dialetti 'storici' di
Basic non hanno i puntatori. A quello pensavo. Confesso che pensavo
anche a Cobol, ma poi ho scoperto che invece Cobol aveva dei puntatori
ancora più scomodi del resto del linguaggio e totalmente non tipati. Non
ho idea di quanto siano stati usati dai cobolisti in pratica.  


 [...]
Manlio Perillo

 testare la loro presenza.
Intendi dire HAVE_XXX  ?
Io intendevo le macro con argomenti... i #define / #ifdef eccetera sono
assai utili, anzi, indispensabili per bloccare le inclusioni.

  beh, un po' dipende anche da quanta portabilità vuoi garantire.
Per una versione altamente non portabile, ma senza salti, si puo'
usare:
template <typename T> myabs(T v) {
  T s = v >> (8*sizeof(T)-1); // assumo 8 bit in un char e lo shift
aritmetico  return (v ^ s) - s; // assumo la rappresentazione in
complemento a due}
Nessuna di queste cose (8bit = 1char, shift aritmetico,
rappresentazione in complemento a due) mi risulta sia definita dallo
standard. Pero' almeno per gli 8bit in un char e la rappresentazione
in complemento a due, sono sicuro sia la scelta della maggior parte
delle piattaforme esistenti.
--*PaN!*, 3 UB in 2 righe... non male, eh?
 
-- 
I'm using an evaluation license of nemo since 149 days.
You should really try it!
http://www.malcom-mac.com/nemo

 incomplemento a due}
La mancanza delle interruzioni di linea in questo client e'
particolarmente fastidiosa.Scusate.
--*PaN!*


 
Perché?
Quella è esattamente la definizione di valore assoluto.