Skocz do zawartości

  •  
  • Mini kompendium
  • MimeTeX
  • Regulamin

Zdjęcie

Program w Java

LICEUM

  • Nie możesz napisać tematu
  • Zaloguj się aby odpowiedzieć
11 odpowiedzi w tym temacie

#1 Jarekzulus

Jarekzulus

    Wielki Analityk

  • +Mods
  • Redaktor
  • 4210 postów
3410
Profesor
  • Płeć:Mężczyzna

Napisano 25.11.2013 - 00:12

Witam, to nie zadanie na już, wiec nie ma ciśnienia :)

 

Problem: Napisz program (w Javie) który to w podanym zakresie wyznaczy najlepsze dwie liczby ( Najlepsze to takie które dają najdokładniejsze przybliżenie liczby \pi)

 

http://matma4u.pl/to...pi/#entry111364

 

Np. W zakresie liczby 1 - 22 najlepsze będą 22 i 7 bo \frac{10}{3}=3,1428 (dwie liczby po przecinku się zgadza z  liczbą \pi)

 

Zakładam ze musi to być program działający na zasadzie brutalnej siły.

 

Więc może działać w taki sposób:

 

1. Wczytaj zakres np. do 10

2. Później sprawdzi pary liczb pod kątem iloczynu i bliskości z liczbą \pi ( z których pierwsza minimum 3 razy większa od drugiej) np. 3,1; 4,1; 5;1; 6,1; 6;2...10,1; 10,2; 10,3;

3. Efekt poszukiwań wypisze (dwa najlepsze wyniki) ( u nas było by to 3,1 i 10,3)

 

 

Chyba że macie inne pomysły. Chce wyznaczyć iloczyn (liczb naturalnych) dający mi ponad dziesięć cyfr z rozwinięcia liczby \pi

 

Z tego co wiem trzeba szukać wśród liczb ponad 100 000 (\frac{104348}{33215}=3,14159265392 daje 9 liczb zgodnych). Oczywiście nie sprawdziłem wszystkich, być może jest iloczyn mniejszych liczb który jest lepszy. Stąd ten praogram

 

 

pozdrawiam


  • 0

:wave: :wave: :wave: Jeśli rzuciłem choć promyczek światła na problem który postawiłeś - podziękuj. pre_1433974176__syg.jpgNad kreską


Afroman

    Kombinator

  • Użytkownik
3
  • Płeć:Kobieta

Napisano 25.09.2011 - 17:55

#2 Ereinion

Ereinion

    Mega Rozkminiacz z Marsa

  • $Jr Admin
  • 2104 postów
1008
Starszy Wykładowca I
  • Płeć:Mężczyzna

Napisano 25.11.2013 - 23:21

Tak jak Ty chcesz to robić to pachnie złożonością kwadratową, więc tak średnio. No ale możnaby dla kolejnych liczb n z danego przedziału patrzeć na \lfloor \pi n \rfloor oraz \lceil \pi n \rceil. O ile te liczby należą do danego przedziału, to każdą z nich dzielimy przez n i patrzymy ile jest cyfr zgodnych z \pi. To już działa w czasie liniowym, więc sensowniej.


  • 1

#3 Jarekzulus

Jarekzulus

    Wielki Analityk

  • +Mods
  • Redaktor
  • 4210 postów
3410
Profesor
  • Płeć:Mężczyzna

Napisano 26.11.2013 - 02:03

Tak tak, dziś też na to wpadłem :)

 

Niebawem napiszę gotowy programik- teraz coś mi się nie kompiluje. Problem z zaokrągleniami i nie wiem jak sprawdzić ile cyfr się zgadza, tj. by program to mi napisał

 

Jak znajdziesz chwilkę skleć coś. Może wpadniesz na eleganckie rozwiązanie :)

 

Pozdrawiam

 

W Excelu zrobiłem tak:

n        n*\pi        k=zaokrąglenie (n*pi)      f=k/n         g=f-pi       |g|           minimum w pewnym zakresie

1

2

 

W ten sposób znalazłem

 

\frac{362783828}{115477679}  :D

 

Niestety w pewnym momencie Excel stwierdził że Pi jest wymierne ;/


Użytkownik Jarekzulus edytował ten post 26.11.2013 - 02:20

  • 0

:wave: :wave: :wave: Jeśli rzuciłem choć promyczek światła na problem który postawiłeś - podziękuj. pre_1433974176__syg.jpgNad kreską


#4 Ereinion

Ereinion

    Mega Rozkminiacz z Marsa

  • $Jr Admin
  • 2104 postów
1008
Starszy Wykładowca I
  • Płeć:Mężczyzna

Napisano 26.11.2013 - 12:44

Trudno oczekiwać od komputera, żeby rozumiał co to są liczby niewymierne. On ma ileś tam bitów na reprezentację każdej liczby, więc nie jest możliwe, żeby przechowywał całe nieskończone rozwinięcie dziesiętne. W Javie masz standardowo coś koło 15 cyfr po przecinku, chyba że pobawisz się biblioteką BigDecimal. 

Wspomniana biblioteka wyeliminuje Ci też problem niechcianych zaokrągleń. 

Do liczenia podłogi i sufitu masz w Javie gotowe Math.ceil i Math.floor.

Sprawdzanie ile jest zgodnych miejsc można różnie. Możesz wypisać obie liczby jako stringi i porównywać znak po znaku albo mnożyć różnicę tych liczb przez 10 dopóki masz coś z przedziału (-1,1). Potem policzyć ile razy pomnożyłeś.


  • 0

#5 Jarekzulus

Jarekzulus

    Wielki Analityk

  • +Mods
  • Redaktor
  • 4210 postów
3410
Profesor
  • Płeć:Mężczyzna

Napisano 27.11.2013 - 03:22

public class PiWymierne
    {
    static public double round(double d, int ic)
        {
          java.text.NumberFormat nf = java.text.NumberFormat.getInstance();
          nf.setMaximumFractionDigits(ic);
          nf.setMinimumFractionDigits(ic);
          return Double.parseDouble((nf.format(d)).replaceAll(",", ".").replaceAll(" ", "") );
    }
    public static void main(String[]args)
    {
        int a=1;
        int doile=414;
        double minimum=1;
        double mianownik=1;
        double licznik=1;
        
        while(a<=doile)
        {
            double k=a*Math.PI;
            double l=round(k, 0);
            double m=l/a;
            double n=Math.abs(Math.PI-m);
            if(n<minimum){minimum=n; mianownik=a; licznik=l; System. out.println("Dla "+l+" przez "+a+" mamy "+m);};
            a++;
        }
        
    }
}

 

To wyżej działa tylko do pewnego momentu. Nie wiem czemu przestaje (Widzisz gdzieś błąd)?

 

Trochę posiedziałem i zrobiłem na BigDecimal,

 

import java.math.*;
import java.util.Scanner;
public class Buffon
    {
    public static void main(String[]args)
    {
        BigDecimal a = new BigDecimal("1");
        BigDecimal doile = new BigDecimal("11");
        BigDecimal minimum = new BigDecimal("1");
        BigDecimal mianownik = new BigDecimal("1");
        BigDecimal licznik = new BigDecimal("1");
        BigDecimal pi = new BigDecimal("3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679");
        
        while((a.compareTo(doile))==-1)
        {
            BigDecimal k=new BigDecimal ("1");
                k=a.multiply(pi);
            BigDecimal l=new BigDecimal ("1");
                l = k.setScale(0, RoundingMode.HALF_UP);
            BigDecimal m=new BigDecimal ("1");
                m=l.divide(a);
            BigDecimal n=new BigDecimal ("1");
                n=(pi.subtract(m)).abs();
            if((n.compareTo(minimum)==-1))
                {minimum=n;
                mianownik=a;
                licznik=l;
                System. out.println("Dla "+l+" przez "+a+" mamy "+m);
                };
            BigDecimal dol=new BigDecimal ("1");
            a=a.add(dol);
        }
        
    }
}

-musiałem statycznie wpisać pi bo nie wiem jak to się przedstawia w Bigdecimal,  Błędów nie pokazuje ale jak pościłem by liczyło wypisało 3 wyniki i zdechło. Co jest nie tak (nie rozumiem komunikatu ;/

 

Zobacz i podpowiedz coś :)


Pozdawiam


Użytkownik Jarekzulus edytował ten post 27.11.2013 - 00:32

  • 0

:wave: :wave: :wave: Jeśli rzuciłem choć promyczek światła na problem który postawiłeś - podziękuj. pre_1433974176__syg.jpgNad kreską


#6 Ereinion

Ereinion

    Mega Rozkminiacz z Marsa

  • $Jr Admin
  • 2104 postów
1008
Starszy Wykładowca I
  • Płeć:Mężczyzna

Napisano 27.11.2013 - 11:21

import java.math.*;

public class Buffon {

    public static void main(String[] args) {
        BigDecimal a = new BigDecimal("1");
        BigDecimal doile = new BigDecimal("10000000");
        BigDecimal minimum = new BigDecimal("1");
        BigDecimal mianownik = new BigDecimal("1");
        BigDecimal licznik = new BigDecimal("1");
        BigDecimal pi = new BigDecimal("3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679");
        BigDecimal dziesiec = new BigDecimal("10");
        BigDecimal jeden = new BigDecimal("1");
        
        while ((a.compareTo(doile)) < 0) {
            BigDecimal k = a.multiply(pi);
            BigDecimal l = k.setScale(0, RoundingMode.HALF_UP);
            BigDecimal m = l.divide(a, 30, RoundingMode.HALF_UP);
            BigDecimal n = (pi.subtract(m)).abs();
            if ((n.compareTo(minimum) < 0)) {
                minimum = n;
                mianownik = a;
                licznik = l;
                int i;
                for (i = 0; n.compareTo(jeden) <= 0; i++) {
                    n = n.multiply(dziesiec);
                }
                System.out.println("Dla " + l + " przez " + a + " mamy "+m+"czyli " + (i-1) + " zgodnych cyfr.");
            }
            a = a.add(jeden);
        }

    }
}

Powinno działać. Czasami to liczenie zgodnych cyfr daje o jeden za duży wynik. Możesz to poprawić jak Ci się chce, albo napisać metodę bazującą na porównywaniu stringów.


  • 1

#7 Jarekzulus

Jarekzulus

    Wielki Analityk

  • +Mods
  • Redaktor
  • 4210 postów
3410
Profesor
  • Płeć:Mężczyzna

Napisano 27.11.2013 - 14:52

Dzieki

 

Powiedz tylko jeszcze co liczysz w:

 

BigDecimal m = l.divide(a, 30, RoundingMode.HALF_UP);

 

I dlaczego tak? Czyżby to robiło błąd? w moim programiku?


  • 0

:wave: :wave: :wave: Jeśli rzuciłem choć promyczek światła na problem który postawiłeś - podziękuj. pre_1433974176__syg.jpgNad kreską


#8 Ereinion

Ereinion

    Mega Rozkminiacz z Marsa

  • $Jr Admin
  • 2104 postów
1008
Starszy Wykładowca I
  • Płeć:Mężczyzna

Napisano 27.11.2013 - 21:49

Tak, to był błąd w Twoim programiku. Chodzi o to, że divide z jednym parametrem dzieli dokładnie, tzn nie zaokrągla w żadnym miejscu po przecinku, z tego powodu jak trafi na liczbę o nieskończonym rozwinięciu dziesiętnym, np \frac{1}{3} to się wysypuje. Ja podając dodatkowe parametry kazałem mu zaokrąglać na 30. miejscu po przecinku. Możesz oczywiście tę liczbę 30 zmniejszyć/zwiększyć wedle uznania.


  • 0

#9 Jarekzulus

Jarekzulus

    Wielki Analityk

  • +Mods
  • Redaktor
  • 4210 postów
3410
Profesor
  • Płeć:Mężczyzna

Napisano 27.11.2013 - 23:12

No niby wiem jak działa BigDecimal (tj. ze liczby są przechowywane niejako jako string) ale jakoś umkneło mi to ;)

 

Dzięki za oświecenie

 

Pozdrawiam

 

p.s. To w takim razie jeszcze jedno pytanko: Ciekawi mnie dlaczego program PiWymierne (na doulbe) się wysypywał w pewnym momencie. Tam nie było problemu z zaokragleniem chyba


  • 0

:wave: :wave: :wave: Jeśli rzuciłem choć promyczek światła na problem który postawiłeś - podziękuj. pre_1433974176__syg.jpgNad kreską


#10 Ereinion

Ereinion

    Mega Rozkminiacz z Marsa

  • $Jr Admin
  • 2104 postów
1008
Starszy Wykładowca I
  • Płeć:Mężczyzna

Napisano 28.11.2013 - 19:54

Program się wysypuje przez funkcję NumberFormat.format() bo ona dla liczb większych od 1000 zwraca Stringa w formacie, którego potem nie rozumie parseDouble(). Ogólnie pisanie własnej funkcji round() to kiepski pomysł.


  • 1

#11 Jarekzulus

Jarekzulus

    Wielki Analityk

  • +Mods
  • Redaktor
  • 4210 postów
3410
Profesor
  • Płeć:Mężczyzna

Napisano 28.11.2013 - 22:56

Ogólnie dzięki :)

 

Ogólnie pisanie własnej funkcji round() to kiepski pomysł.

 

Eeee tam kiepski, zawsze takie coś rozpędza Ci szare komórki :) szczególnie jeśli nie chce działać.

 

Pozdrawiam


  • 0

:wave: :wave: :wave: Jeśli rzuciłem choć promyczek światła na problem który postawiłeś - podziękuj. pre_1433974176__syg.jpgNad kreską


#12 fajansik

fajansik

    Nowicjusz

  • Użytkownik
  • 2 postów
0
Neutralny
  • Płeć:Mężczyzna

Napisano 02.12.2013 - 18:06

No - skąd ja to znam :D


  • 0