Newsgroup: it.comp.lang.vo-clipper
Titolo: Round

Visto che sulla round si è scritto tanto vi posto
una funzione che ho trovato sul news internazionale
FUNCTION FT_Round(v AS FLOAT,d AS INT) AS FLOAT
 // Author  : Mathias Håkansson
 // Email  : 
mathias....@tendata.se
 // Date   : 18 October 1999
 // --------------
 file://g Math
 file://l Rounding function for floating point
 file://p Rounding function for floating point
 file://a FLOAT <v> The number to round
 file://a INT <d> Number of decimals
 file://r Rounded value as FLOAT
 file://j FUNCTION:ft_round        round
 LOCAL fraction AS FLOAT
 LOCAL roundval,diff AS FLOAT
 roundval := v*POW(10,d)
 fraction := Frac(roundval)
 roundval -= fraction
 diff := fraction - 0.5
 IF diff > 0
  roundval += 1
 ELSE
  file://d Why this?
  file://d Well, try Round(128.015,2). The result is 128.01 which is
incorrect!
  file://d Due to the nature of floating point values rounding errors can
occur.
  file://d These lines makes sure that the value is rounded upwards if the
fraction
  file://d is really close to 0.5.
  IF Abs(diff) < POW(10,-10)
   roundval += 1
  ENDIF
 ENDIF
 RETURN roundval*POW(10,-d)

 FUNCTION FT_Round(v AS FLOAT,d AS INT) AS FLOAT
Mi sembra molto ma molto poco efficiente. L'elevazione a potenza,
utilizzata nella funzione, è molto lenta...
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


Io avrei da dirne anche sull'Int() e Fract().
Ciao,
    Fabrizio Malaguti
P.S.
Avevo confezionato anch'io una Round() ma dal momento che era solo per
qualche centesimo di secondo piu' veloce della tua ho lasciato perdere.
Però la cosa sorprendente è la velocità della routine in clipper paragonata
alla versione mista Clipper/C. Forse che in realtà le funzioni che
manipolano le stringhe in realtà sono scritte in ASM?
P.S.2
Se pensate che, per pura didattica possa interessare anche la mia versione
di round(), fatemi sapere.

manipolano le stringhe in realtà sono scritte in ASM?
Quasi tutte le funzioni di libreria sono scritte in ASM.
ciao, acc.   
a...@libero.it

 di round(), fatemi sapere.
Interessa senz'altro. Ma è altrettanto compatta? Comunque inviala. La
esaminerò con interesse...


 EMG
Ecco la funzione Round3().
In effetti S tutto tranne che compatta. La routine S di tipo esaustiva
ovvero anzichS arrivare alla soluzione tramite una routine generica
ho tentato la via di prevedere tutti i casi possibili.
Prima di essere linciato una breve spiegazione:
Ho voluto evitare tutte funzioni tipo Left(), Substr(), Asc(), Replicate(),
ecc
in quanto le ritenevo lente preferendo una DO CASE con tutti i possibili
casi ( o perlomeno tutti quelli pi- reali ) pensando di sfruttare il
parallelismo implicito dei processori classe Pentium. Peccato che il
Clipper 5.2e sia stato sviluppato prima della nascita di detti processori.
Il risultato S stato scarso. La velocit. non S molto buona se paragonata
alla Round() nativa. Non S molto pi- veloce rispetto a quella di EMG.
Infine ha qualche diffetto di allineamento. Per ultimo, come dicevo
all'inizio, non S per niente compatta anzi se non l'avessi scritta io
direi che S opera di un cretino. In pratica un fiasco completo (almeno per
lo
scopo che mi ero prefisso).
Effettivamente non mi aspettavo che le funzioni che manipolano le stringhe
in
Clipper fossero cos  veloci a tal punto da rendere quasi inutile il
tentativo
di creare delle routine in C per velocizzare alcuni punti in apperenza
critici
della routine di EMG (mi riferisco ad una delle prime in quanto ho perso il
conto di tutte le versioni). Come dice anche ACC probabilmente le funzioni
Clipper sono scritte in ASM. Se cos  S perchS impazzire a crearne di nuove
in C ?
Quando avro' pi- tempo, comunque vorrei fare un tentativo con VO per
vedere se l'approccio di tipo esaustivo paga con un compilatore ottimizzato
con i processori dell'ultima generazione oppure se occorre aspettare dei
compilatori che permettano il parallelismo esplicito nei linguaggi di
programmazione ( CA VO 3.x su OS WINDOWS XP con INTEL ITANIUM a 64 bit ? ).
FUNCTION ROUND3(V,D)
   LOCAL C,P,CD,DD,S,K,KK,F
   F := V > 0
   C := STR(V)
   IF (P := AT(".",C)) = 0
      C := C+"."
   ENDIF
   IF D >= 0
      K := P+D
      KK := VAL(SUBSTR(C,K+1,1))
      DD := D-Len(C)+P+1
      IF     DD <= 0
         // nulla
      ELSEIF DD = 1
         C := C+"0"
      ELSEIF DD = 2
         C := C+"00"
      ELSEIF DD = 3
         C := C+"000"
      ELSEIF DD = 4
         C := C+"0000"
      ELSEIF DD = 5
         C := C+"00000"
      ELSEIF DD = 6
         C := C+"000000"
      ELSEIF DD = 7
         C := C+"0000000"
      ELSEIF DD = 8
         C := C+"00000000"
      ELSEIF DD = 9
         C := C+"000000000"
      ELSEIF DD = 10
         C := C+"0000000000"
      ELSEIF DD = 11
         C := C+"00000000000"
      ELSEIF DD = 12
         C := C+"000000000000"
      ELSEIF DD = 13
         C := C+"0000000000000"
      ELSEIF DD = 14
         C := C+"00000000000000"
      ELSEIF DD = 15
         C := C+"000000000000000"
      ELSEIF DD = 16
         C := C+"0000000000000000"
      ELSEIF DD = 17
         C := C+"00000000000000000"
      ENDIF
      C := SUBSTR(C,1,K)
      IF KK >= 5
         IF     D = 0
            V := VAL(C) + IIF(F, 1, -1)
         ELSEIF D = 1
            V := VAL(C) + IIF(F, 0.1, -0.1)
         ELSEIF D = 2
            V := VAL(C) + IIF(F, 0.01, -0.01)
         ELSEIF D = 3
            V := VAL(C) + IIF(F, 0.001, -0.001)
         ELSEIF D = 4
            V := VAL(C) + IIF(F, 0.0001, -0.0001)
         ELSEIF D = 5
            V := VAL(C) + IIF(F, 0.00001, -0.00001)
         ELSEIF D = 6
            V := VAL(C) + IIF(F, 0.000001, -0.000001)
         ELSEIF D = 7
            V := VAL(C) + IIF(F, 0.0000001, -0.0000001)
         ELSEIF D = 8
            V := VAL(C) + IIF(F, 0.00000001, -0.00000001)
         ELSEIF D = 9
            V := VAL(C) + IIF(F, 0.000000001, -0.000000001)
         ELSEIF D = 10
            V := VAL(C) + IIF(F, 0.0000000001, -0.0000000001)
         ELSEIF D = 11
            V := VAL(C) + IIF(F, 0.00000000001, -0.00000000001)
         ELSEIF D = 12
            V := VAL(C) + IIF(F, 0.000000000001, -0.000000000001)
         ELSEIF D = 13
            V := VAL(C) + IIF(F, 0.0000000000001, -0.0000000000001)
         ELSEIF D = 14
            V := VAL(C) + IIF(F, 0.00000000000001, -0.00000000000001)
         ELSEIF D = 15
            V := VAL(C) + IIF(F, 0.000000000000001, -0.000000000000001)
         ELSEIF D = 16
            V := VAL(C) + IIF(F, 0.0000000000000001, -0.0000000000000001)
         ELSEIF D = 17
            V := VAL(C) + IIF(F, 0.00000000000000001, -0.00000000000000001)
         ENDIF
      ELSE
         V := VAL(C)
      ENDIF
   ELSE
      K := P+D-1
      KK := VAL(SUBSTR(C,K+1,1))
      IF     D = -1
         C := SUBSTR(C,1,K) + "0."
         S := 10
      ELSEIF D = -2
         C := SUBSTR(C,1,K) + "00."
         S := 100
      ELSEIF D = -3
         C := SUBSTR(C,1,K) + "000."
         S := 1000
      ELSEIF D = -4
         C := SUBSTR(C,1,K) + "0000."
         S := 10000
      ELSEIF D = -5
         C := SUBSTR(C,1,K) + "00000."
         S := 100000
      ELSEIF D = -6
         C := SUBSTR(C,1,K) + "000000."
         S := 1000000
      ELSEIF D = -7
         C := SUBSTR(C,1,K) + "0000000."
         S := 10000000
      ELSEIF D = -8
         C := SUBSTR(C,1,K) + "00000000."
         S := 100000000
      ELSEIF D = -9
         C := SUBSTR(C,1,K) + "000000000."
         S := 1000000000
      ELSEIF D = -10
         C := SUBSTR(C,1,K) + "0000000000."
         S := 10000000000
      ELSEIF D = -11
         C := SUBSTR(C,1,K) + "00000000000."
         S := 100000000000
      ELSEIF D = -12
         C := SUBSTR(C,1,K) + "000000000000."
         S := 1000000000000
      ELSEIF D = -13
         C := SUBSTR(C,1,K) + "0000000000000."
         S := 10000000000000
      ELSEIF D = -14
         C := SUBSTR(C,1,K) + "00000000000000."
         S := 100000000000000
      ELSEIF D = -15
         C := SUBSTR(C,1,K) + "000000000000000."
         S := 1000000000000000
      ELSEIF D = -16
         C := SUBSTR(C,1,K) + "0000000000000000."
         S := 10000000000000000
      ELSEIF D = -17
         C := SUBSTR(C,1,K) + "00000000000000000."
         S := 100000000000000000
      ENDIF
      V := VAL(C)
      IF KK >= 5
         IF F
            V += S
         ELSE
            V -= S
         ENDIF
      ENDIF
   ENDIF
RETURN V

 Ecco la funzione Round3().
Come ho detto ad acc, non mi va più di continuare. Comunque ne ho almeno
confrontato la velocità che mi è sembrata paragonabile alle altre
funzioni e quindi sembra che l'esplorazione di tutti i singoli casi non
abbia prodotto i risultati sperati.
