Newsgroup: it.lavoro.informatica
Titolo: strano comportamento codice java

Questa successione numerica definita per ricorrenza deve dare ovviamente sempre lo stesso valore per ogni termine ( cioè sempre 1/77) , invece da tutti valori diversi! 
 
 public class successione {
 
    public static void main(String[] args) {
 
        int n = 10;
        double s = 1.0/77.0;
        System.out.print("First " + n + " terms: ");
 
        for (int i = 1; i <= n; ++i)
        {
            System.out.print(s + " x ");
 
            double  r = 78.0 * s - 1.0;
            s = r;
 
        }
    }
}
 
ciao


Non so se ti hanno gia' rispsto (perché alcuni di quelli che potrebbero 
averti risposto sono da tempo nei miei filtri) ma secondo me non è strano.
 
Quando si lavora con i numeri in floating point bisogna considerare che 
i numeri reali sono infiniti mentre la macchina può rappresentare solo 
un numero finito di numeri reali, per cui ad esempio il numero 1/77 non 
è detto che sia tra quelli rappresentabili sulla macchina e quindi il 
risultato di 1.0/77.0 potrebbe non essere 1/77 ma sarà il numero reale 
che la macchina può rappresentare al suo interno che sia il più
possibile vicino a 1/77. Quindi il risultato di 1.0/77.0 potrà
essere 1/77+err dove err e' l'errore che la macchina compie 
nell'approssimare il risultato esatto [in altre parole err = 
(1.0/77.0)-1/77]
 
Quindi quando poi (i=1) chiedi alla macchina di eseguire 78.0*s-1.0,
poiché s contiene 1/77+err e non esattamente 1/77, r non varrà 
esattamente 1/77 ma 78.0*(1/77+err)-1.0
 
- anzi per la verità sarebbe
(78.0*(1/77+err)-1.0)+err2 perché anche 78.0*(1/77+err)-1.0 non è
detto che sia rappresentabile con precisione infinita. Ma per semplicità 
si può considerare che anche se fosse err2=0, i numeri stampati 
potrebbero comunque non essere uguali -
 
considerando err2=0 si ha comunque  che
quando  i=2
ad r verrà assegnato il valore 78.0[(78.0*(1/77+err)-1.0]-1.0
e quindi tale valore sarà essegnato anche ad s .
 
(anche qui sarebbe in realtà (78.0[(78.0*(1/77+err)-1.0]-1.0+err3, ma 
facciamo ancora finta che err3=0)
 
 
quando i = 3, ad r sarà assegnato il valore 78.0* 
{78.0*(78.0*(1/77+err)-1.0)-1.0}-1.0
e così via.
 
Inoltre c'è da tenere presente che, almeno in teoria, proprio perché la 
macchina non può rappresentare tutti i numeri reali, anche 1.0, 78.0, 
77.0 potrebbero non essere rappresentati senza errori nella macchina
(non so se esiste qualcosa che garantisca che i numeri interi siano 
rappresentati con precisione infinita. Se esiste qualcosa in questo 
senso io non ne sono a conoscenza).
 
Così ad occhio e croce, se vuoi che s sia sempre pari a 1.0/77.0 (o a 
1/77+err) a dovresti provare a cambiare l'assegnamento s=r con qualcosa 
del tipo:
 
if(valore_assoluto(r-s) < my_epsilon) s=1.0/77.0;
 
dove my_epsilon è lo scarto che ritieni accettabile tra 1/77 e 1/77+err 
(ovviamente se specifichi un my_epsilon < err potrebbe non funzionare)
 
Ciao,
Marco
 
 
-- 
Questa e-mail è stata controllata per individuare virus con Avast antivirus.
https://www.avast.com/antivirus
 
 


'ndo sta la ricorrenza?
 


Qualcuno le chiama successioni ricorsive, qualcuno
successioni definite per ricorrenza (o ricorsione), ecc.
 
puoi vedre ad esempio qui:
 
https://www.youmath.it/domande-a-risposte/view/1891-successioni-definite-per-ricorrenza.html
 
 
o qui
 
https://www.mat.uniroma1.it/mat_cms/materiali/2009-2010/finzivita-15035-ricorrenza_LPC.pdf
 
 
o qui:
 
https://it.wikipedia.org/wiki/Successione_ricorsiva
 
 
 
Quella del suo esempio dovrebbe potersi scrivere come segue
 
 
n(0)=1/77
 
n(i)=78 * n(i-1) - 1  per i=1,2,3...
 
in cui effettivamente
dovrebbe essere vero che n(i)=1/77 per ogni i=0,1,2,...
 
 
Però dato che le macchine non hanno precisione infinita,
salvo casi particolari sarà difficile avere n(i) tutti uguali con il
codice che ha scritto lui.
 
Ciao,
Marco.


Il 09/09/20 02:38, pino mugo ha scritto:

col COBOL sti problemi non esistono....
se devi fare ste ose impara il COBOL!!!!
 
-- 
grigio


Ricorsione! Non ricorrenza, my bad.
 

 se devi fare ste ose impara il COBOL!!!!
 
Il Cobol non fa i conti?
 


potresti argomentare in modo da farti capire invece di parlare per assiomi?
 
-- 
The three most dangerous things in the world are a programmer with a 
soldering iron, a hardware type with a program patch and a user with an 
idea.
 
“Alles hat ein Ende, nur die Wurst hat zwei”

 Marco 
 
grazie ho capito.

Il 10/09/20 13:26, grigio ha scritto:

Ma certo che questi problemi esistono se si usano i floating point,sia 
in COBOL che in altri linguaggi, e' indifferrente il linguaggio usato.
Ora mi dirai che il COBOL ha i fixed point per ovviare a questi problemi 
ed e' vero, ma li ha anche java, si chiamano big decimal
 
 
 
-- 
|___|

 
 
Ho provato, ma il problema rimane, ecco il codice modificato (è corretto così  l'uso del bigdecimal?) :
 
import java.math.BigDecimal;
public class t{
 
     public static void main(String []args){
 
            int n = 5;            
 
BigDecimal b = new BigDecimal("77");
BigDecimal d = new BigDecimal("1");
BigDecimal s = d.divide(b,java.math.MathContext.DECIMAL128);
 
 
         for (int i = 1; i <= n; ++i)
         {
             System.out.print(s + " x ");
             BigDecimal m = new BigDecimal("78");
            m = m.multiply(s , java.math.MathContext.DECIMAL128);
            m = m.subtract(d , java.math.MathContext.DECIMAL128);
            s = m;
            }
 
         }
}
 

Il 15/09/20 20:38, pino mugo ha scritto:

Non so se e' per DECIMAL128 ma in un programma che calcola il pigreco a 
N cifre (fatto per comparare a c++) avevo usato
RoundingMode.HALF_UP e MathContext.UNLIMITED
 
 
 
import java.math.*;
 
 
public class pigreco {
 
	private static void print(String s,int n) {
		if (s.length() < n)
			n=s.length();
		if (n < 3)  {
  			System.out.println(s);
			return;
		}
		System.out.println(s.substring(0,2));
		int j=1;
		for (int i=2;i < n;++i) {
			System.out.print(s.charAt(i));
			if (j % 10 == 0)
				System.out.print(" ");
			if (j % 170 == 0)
				System.out.println("");
			++j;			
		}
		System.out.println("");
	}
 
	public static void main(String args[]){
		final int n=Integer.parseInt(args[0]);
		final boolean isprint=Integer.parseInt(args[1]) != 0;
		final BigDecimal n16=new BigDecimal(1).divide(new BigDecimal(16), 
MathContext.UNLIMITED);
  		BigDecimal s=new BigDecimal(0);
		for (int i=0;i < n;++i) {
			final int n8=8 * i;
			final BigDecimal n81=new BigDecimal(n8 + 1);
			final BigDecimal n84=new BigDecimal(n8 + 4);
			final BigDecimal n85=new BigDecimal(n8 + 5);
  			final BigDecimal n86=new BigDecimal(n8 + 6);
			final BigDecimal a = new 
BigDecimal(4).divide(n81,n,RoundingMode.HALF_UP);
			final BigDecimal b = new 
BigDecimal(2).divide(n84,n,RoundingMode.HALF_UP);
			final BigDecimal c = new 
BigDecimal(1).divide(n85,n,RoundingMode.HALF_UP);
			final BigDecimal d = new 
BigDecimal(1).divide(n86,n,RoundingMode.HALF_UP);
			s=s.add(a.subtract(b).subtract(c).subtract(d).multiply(n16.pow(i)));
		}
		if (isprint)
			print(s.toPlainString(),n);
	}
};
 
 
 
 
 
 
-- 
|___|