Newsgroup: it.comp.java
Titolo: Nuneri a virgola fissa

Ciao a tutti, ho cercato di implementare i numeri a virgola fissa [non
chiedetermi perche' :-) ]
con parte intera e parte decimale messi in due interi, la parte decimale e'
come l'euro,
di 2 cifre e basta.
Ho implementato somme e moltiplicazioni e cavoli vari, ma mi sembra che i
numeri che mi escono
sono leggermente sballati :-( ... lo so, lo so, la matematica, la
matematica... effettivamente non
ricordo come vanno gestiti i numeri a virgloa fissa (ah, il calcolo
numerico!)
Bon, mi dite se vedete qualche grossa cavolata, se ho scavolato qualche
operazione, etc, etc...?
Che dimentico? Ah, il codice...
Si, l'ho chiamata Float, chiamatela come volete,
ovviamente copyright, fateci quello che volete :-)
Bye
Cattivik
public class Float
{
    private int pi=0;
    private int pd=0;
    public Float(int pi, int pd)
    {
        this.pd=pd;
        this.pi=pi;
    }
    public Float(int pi)
    {
        this.pd=0;
        this.pi=pi;
    }
    public boolean isZero()
    {
        return ((pi==0)&& (pd==0));
    }
    public boolean isPositive()
    {
     return (pi*100+pd>0);
    }
    public boolean isNegative()
    {
     return (pi*100+pd<0);
    }
    public int getPi()
    {
        return pi;
    }
    public int getPd()
    {
        return pd;
    }
    public void setPi(int pi)
    {
        this.pi=pi;
    }
    public void setPd(short pd)
    {
        this.pd=pd;
    }
    public Float sum(Float another)
    {
        int va=another.getPi()*100+another.getPd()+pi*100+pd;
        pi=va/100;
        pd=Math.abs(va%100);
        return this;
    }
    public Float sub(Float another)
    {
        int va=another.getPi()*100+another.getPd()-pi*100+pd;
        pi=va/100;
        pd=Math.abs(va%100);
        return this;
    }
    public Float mul(Float another)
    {
        int va=another.getPi()*100+another.getPd()*pi*100+pd;
        pi=va/10000;
        pd=Math.abs((va/100)%100);
        return this;
    }
    public Float inverti()
    {
        int v=(100/(pi*100+pd));
        pi=v/100;
        pd=Math.abs(v%100);
        return this;
    }
    public Float div(Float dividendo)
    {
        return mul(dividendo.inverti());
    }
    public Float clone()
    {
        return new Float(pi,pd);
    }
    public String toString()
    {
        return pi+","+pd;
    }
}

Se si compila con j2se dovete togliere clone, e mettrere
public Float duplica()
{
return new Float(pi,pd);
}
oppure far tornare Object al clone.
Grazie ad Orzibaf che me lo ha fatto notare,
la classe e' per J2ME, il cui Object non ha il metodo clone(), ecco perche'
io non avevo problemi di overriding di metodi

 numerico!)
[snip]
guarda a occhio e croce hai una perdita di precisione essenzialmente sulle 
divisioni.
comunque l;idea e' carina.
Ciao

 Ciao
Ti ringrazio,
della perdita di precisione non mi interessa, nel senso che per me e' gia'
un lusso
averli :-)
Ma gli algoritmi di addizione, sottrazione, moltiplicazione e inversione ti
sembrano giusti?

 io non avevo problemi di overriding di metodi
Adesso mi torna tutto !!!!
Due giorni di discussioni e il j2me non ha Object.clone() ..... mortacci!!!
-- 
Ciao. Fabrizio. ( icq: 241182067 )
< MISTAH KURTZ -- HE DEAD.
                A penny for the Old Guy> 
(T.S. Elliot: the hollow men)

L'idea è carina ma secondo me (bada bene che non sono molto esperto di
programmazione e potrei sbagliarmi di brutto) c'è da lavorarci ancora un po'
su. Allora, ti dico un po' delle mie impresioni così a pelle, perchè per ora
sono tante e un po' confuse... poi magari via via che si va avanti con la
discussione tutto si ordina!
- Tu dici che vuoi numeri con due cifre decimali, ma non da tutte le parti
poni vincoli a pd (che immagino stia per "parte decimale") in modo che non
superi 100 (lo fai nel risultato delle operazioni, ma ed esempio non lo fai
nel metodo setPD() ). Questo potrebbe orignarti dei problemi nei calcoli se
pin seguito ad qualche operazione pd supera 100...
- C'è un prolema sulla gestione del segno: chi lo tiene? Dovrebbe o essere
gestito a parte, imponendo quindi che sia pi che pd siano sempre maggiori di
0, oppure essere il segno di pi finchè questo è diverso da 0, e il segno di
pd quando pd=0. Non vedo però da nessuna parte traccia di questo controllo e
se succede che pi e pd siano entrambi negativi non capisco bene che numero
si sta rappresentando...
- Nel metodo sub() c'è un'errore di segno: alla fine della prima riga deve
esserci -pd e non +pd
- La tecninca che usi per ricostruire pd e pi dopo ogni operazione
matematica sballa il segno se il risultato è un numero negativo con valore
assoluto minure di 1 (in più credo che negli altri casi "math.abs" sia
superfluo)
- Nel metodo mul() hai lasciato in po' di parentesi:
"another.getPi()*100+another.getPd()*pi*100+pd" deve diventare "[
another.getPi()*100+another.getPd()]*[pi*100+pd]" dove le parentesi quadre
le ho messe per chiarezza, ma nel codice devono essere tonde.
- quando inverti fai una divisione intera, il che non mi pare molto
consigliabile... se inverti 1,5 la prima riga del tuo metodo fa 100/150 =0 e
l'inverso di 1,5, il che implica che 1,5*0=1... mica male!
E per il momento mi pare che basti...
Un'ultima cosa: io fossi te prima di andare avanti su questa strada mi
chiederei se non sia il caso di gestire il numero con una sola variabile
inetera che rappresenta i centesimi (non la parte decimale, ma i
centesimi... 10,23 --> 1023): in questo modo potresti sfruttare con molta
più semplicità le operazioni tra interi e non avresti il problema del segno
e del pd<100 da gestire...
Buon lavoro
Giacomo


Ti ringrazio... allego la versione modificata... la chiamo Float2 per non
confonderla con java.lang.Float
Ciao
Pietro
public class Float2
{
    // parte intera
    private int pi=0;
    // parte decimale
    private int pd=0;
    public Float2(int pi, int pd)
    {
        assegnaPd(pd);
        this.pi=pi;
    }
    public Float2(int pi)
    {
        this.pd=0;
        this.pi=pi;
    }
    private void assegnaPd(int val)
    {
      if (val<100)
        this.pd=val;
      else
        assegnaPd(val/10);
    }
    public boolean isZero()
    {
        return ((pi==0)&& (pd==0));
    }
    public boolean isPositive()
    {
     return (pi*100+pd>0);
    }
    public boolean isNegative()
    {
     return (pi*100+pd<0);
    }
    public int getPi()
    {
        return pi;
    }
    public int getPd()
    {
        return pd;
    }
    public void setPi(int pi)
    {
        this.pi=pi;
    }
    public void setPd(int pd)
    {
        assegnaPd(pd);
    }
    public Float2 sum(Float2 another)
    {
        int va=(another.getPi()*100+another.getPd())+(pi*100+pd);
        pi=va/100;
        assegnaPd(Math.abs(va%100));
        return this;
    }
    public Float2 sub(Float2 another)
    {
        int va=(another.getPi()*100+another.getPd())-(pi*100+pd);
        pi=va/100;
        assegnaPd(Math.abs(va%100));
        return this;
    }
    public Float2 mul(Float2 another)
    {
        int va=(another.getPi()*100+another.getPd())*(pi*100+pd);
        pi=va/10000;
        assegnaPd(Math.abs((va/100)%100));
        return this;
    }
    public Float2 inverti()
    {
        int v=(100/(pi*100+pd));
        pi=v/100;
        assegnaPd(Math.abs(v%100));
        return this;
    }
    public Float2 div(Float2 dividendo)
    {
        return mul(dividendo.inverti());
    }
    public Float2 duplica()
    {
        return new Float2(pi,pd);


Io userei una sola variabile interna, magari un long pressapoco cosi':
Perdonate gli errori, non uso Java da 3 anni e non ho compilato il codice:
Si dovrebbero aggiungere controlli per le assegnazioni che non alterino il
segno. P.es. il costruttore con pi, pd dovrebbe dare pi e pd con lo stesso
segno
public class Float
{
private long val=0;
public Float (Float another){
val = another.val;
}
public Float(int pi, int pd)
{
this.val=pi*100+pd;
}
public Float(int pi)
{
this.val=pi * 100;
}
public boolean isZero()
{
return val == 0;
}
public boolean isPositive()
{
return val > 0;
}
public boolean isNegative()
{
return val < 0;
}
public int getPi()
{
return val/100;
}
public int getPd()
{
return val % 100;
}
public void setPi(int pi)
{
this.val=pi * 100;
}
public void setPd(short pd)
{
this.val = this.val / 100 * 100 + pd;
}
public Float sum(Float another)
{
this.val += another.val;
return this;
}
public Float sub(Float another)
{
this.val -= another.val;
return this;
}
public Float mul(Float another)
{
this.val = this.val * another.val / 100;
return this;
}
public Float inverti()
{
val = 100/val;
return this;
}
public Float div(Float dividendo)
{
val = val * 100 / dividendo.val;
return val;
}
public Float clone()
{
return new Float(this);
}
public String toString()
{
return (val/100)+","+(val%100);
}
}

Ecco la versione elaborata con tutti i vostri suggerimenti,
non sono convinto dell'inversione e della divisione, faro' qualche prova
public class Float
{
  private long val=0;
  public Float(int parteIntera, int parteDecimale)
  {
    this.val=parteIntera*100+parteDecimale;
  }
  public Float(int parteIntera)
  {
    this.val=parteIntera * 100;
  }
  public Float()
  {
    this.val=0;
  }
  private void assegnaPd(int nval)
  {
    if (nval<100)
      {
        val=val - val % 100;
        val+=nval;
      }
    else
      assegnaPd(nval/10);
  }
  public boolean isZero()
  {
    return val == 0;
  }
  public boolean isPositive()
  {
    return val > 0;
  }
  public boolean isNegative()
  {
    return val < 0;
  }
  public int getParteIntera()
  {
    return (int)val/100;
  }
  public int getParteDecimale()
  {
    return (int)val % 100;
  }
  public void setParteIntera(int parteIntera)
  {
    int v=(int)val %100;
    val=parteIntera * 100 + v;
  }
  public void setParteDecimale(int parteDecimale)
  {
    assegnaPd(parteDecimale);
  }
  public Float sum(Float another)
  {
    this.val += another.val;
    return this;
  }
  public Float sub(Float another)
  {
    this.val -= another.val;
    return this;
  }
  public Float mul(Float another)
  {
    this.val = this.val * another.getRappresentazione() / 100;
    return this;
  }
  public Float inverti()
  {
//    val = 100/val;
    return this;
  }
  public long getRappresentazione()
  {
    return val;
  }
  public Float div(Float dividendo)
  {
    val = val * 100 / dividendo.getRappresentazione();
    return this;
  }
  public Float duplica()
  {
    return new Float(getParteIntera(), getParteDecimale());



In effetti non fungono... ciao a tutti, a lunedi'.
[CUT]