Newsgroup: it.comp.lang.vo-clipper
Titolo: Nuova versione ROUND2() senza operazioni

Cari amici, ecco una nuova versione "ripensata" della ROUND2() senza
operazioni. Ho praticamente "enumerato" tutti i casi possibili ed ho
inoltre tirato fuori la funzione che incrementa di uno un numero
rappresentato in una stringa:
FUNCTION ROUND2( nValue, nDecimals )
    LOCAL cValue := STR( nValue )
    LOCAL nDotPos := AT( ".", cValue )
    IF nDotPos = 0
        IF nDecimals = 0
            RETURN VAL( cValue )
        ELSEIF nDecimals > 0
            RETURN VAL( cValue + "." + REPLICATE( "0", nDecimals ) )
        ELSE
            IF SUBSTR( cValue, LEN( cValue ) + nDecimals + 1 ) < "5"
                RETURN VAL( LEFT( cValue, LEN( cValue ) + nDecimals ) +
REPLICATE( "0", -nDecimals ) )
            ELSE
                RETURN VAL( STRINC( LEFT( cValue, LEN( cValue ) +
nDecimals ) ) + REPLICATE( "0", -nDecimals ) )
            ENDIF
        ENDIF
    ELSE
        IF nDecimals = 0
            IF SUBSTR( cValue, nDotPos + 1 ) < "5"
                RETURN VAL( LEFT( cValue, nDotPos - 1 ) )
            ELSE
                RETURN VAL( STRINC( LEFT( cValue, nDotPos - 1 ) ) )
            ENDIF
        ELSEIF nDecimals > 0
            cValue += REPLICATE( "0", nDecimals - LEN( cValue ) +
nDotPos )
            IF SUBSTR( cValue, nDotPos + nDecimals + 1 ) < "5"
                RETURN VAL( LEFT( cValue, nDotPos + nDecimals ) )
            ELSE
                RETURN VAL( STRINC( LEFT( cValue, nDotPos + nDecimals )
) )
            ENDIF
        ELSE
            IF SUBSTR( cValue, nDotPos + nDecimals ) < "5"
                RETURN VAL( LEFT( cValue, nDotPos + nDecimals - 1 ) +
REPLICATE( "0", -nDecimals ) )
            ELSE
                RETURN VAL( STRINC( LEFT( cValue, nDotPos + nDecimals -
1 ) ) + REPLICATE( "0", -nDecimals ) )
            ENDIF
        ENDIF
    ENDIF
    RETURN VAL( cValue )
STATIC FUNCTION STRINC( cValue )
    LOCAL nPos := LEN( cValue )
    LOCAL cChr
    WHILE nPos >= 0
        cChr = SUBSTR( cValue, nPos, 1 )
        IF cChr = "."; nPos--; LOOP; ENDIF
        IF cChr = "+" .OR. cChr = "-"
            IF nPos = 1
                cValue = cChr + " " + SUBSTR( cValue, 2 )
                nPos = 2
            ELSE
                cValue = SUBSTR( cValue, 2, nPos - 1 ) + " " + SUBSTR(
cValue, nPos + 1 )
            ENDIF
        ENDIF
        IF cChr < "0"; cChr = "0"; ENDIF
        IF cChr < "9"
            RETURN LEFT( cValue, nPos - 1 ) + CHR( ASC( cChr ) + 1 ) +
SUBSTR( cValue, nPos + 1 )
        ELSE
            cValue = LEFT( cValue, nPos - 1 ) + "0" + SUBSTR( cValue,
nPos + 1 )
        ENDIF
        nPos--
    ENDDO
    RETURN cValue
Se me la volete provare...
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

 Se me la volete provare...
Round2(Val("123.5"),0)  ==> 124 (ma allineato a sinistra)
Avevo gia incontrato questo problema quando ho fatto la mia round2 con le
stringhe. Puoi risolverlo facendo return val( space(10) + cNumero ) (ricordi
il discorso sulla formattazione dei numeri in Clipper, inserita
implicitamente nel numero stesso ?)
Ciao.
Davide.

 Round2(Val("123.5"),0)  ==> 124 (ma allineato a sinistra)
Uhm... riflettiamo un momento... siamo sicuri che questo non sia, in
realtà, il comportamento corretto? Se provi a scrivere
? VAL( "123.5" )
vedi che l'allineamento è in effetti a sinistra. A me sembra che sia la
ROUND(), in questo caso, a sbagliare. La funzione dovrebbe mantenere
l'allineamento del valore originale e non inventarsene uno. Che ne
pensate?
Guardate anche questo:
? VAL( " 123.5" )
? ROUND2( VAL( " 123.5" ), 0 )
Come potete notare anche in questo caso viene conservato l'allineamento
mentre la ROUND() si ostina ad allineare il valore a 10 caratteri. Altro
esempio, anche più importante:
? ROUND2( FIELD -> quantita, 0 )
dove quantita è un campo numerico da cinque cifre. Ebbene, anche in
questo caso la ROUND() originale sbaglia allineando a 10 caratteri. Come
ci dobbiamo comportare, secondo voi?
EMG
--


 pensate?
ecco spiegate le perplessità che avevo nella necessità di replicare
esattamente l'allineamento della round originale.
Il caso delle stampe che ipotizzavi giorni fa è comunque valido.
Secondo me, o fai una round2 che sia allineata come la round, oppure lasci
stare del tutto l'allineamento e ti preoccupi solo che il valore numerico
sia esatto, lasciando a Transform il compito di allineare i risultati.
Ciao.
Davide.


Non sono molto d'accordo. Io non mi ero, in effetti, mai accorto di quel
comportamento della ROUND() originale. O forse magari ci ho combattuto
senza rendermi conto che dipendeva da quella. Se me ne fossi reso conto
avrei sicuramente cercato di correggerla da subito. Infatti non ritengo
accettabile un disallineamento del genere. Io mi sono sempre basato sul
fatto che le cifre specificate in un campo rimanessero invariate a
video...


 video...
ricordi quando ti dicevo che non mi sono mai fidato degli allineamenti
"automatici" di funzioni tipo "?" ?
Di fatto, se non ti sei mai accorto prima di questo output, i tuoi programmi
(o quelli di qualcun altro) risulterebbero disallineati, se "correggi"
l'allineamento della round originale.
Sempre se di correzione si puň parlare: altri infatti non si sono mai basati
sul fatto che le cifre specificate in un campo dovessero per forza restare
invariate a video. Io personalmente ho campi con diversi decimali nelle
tabelle, che poi posso stampare con piů o meno cifre a seconda che il
cliente le voglia o meno.
Ciao.
Davide.

 l'allineamento della round originale.
Si, in effetti potrebbe succedere. Ok, allora vada per la piena
compatibilità.
