Gyakorlati alapok

A kör négyszögesítése

 

Az alcímet könnyen tréfának vehetjük és ilyen célból sokszor talán el is sütöttük, noha a problémával már ógörög matematikusok is szembesültek. Őket elsősorban egy kör területével egyenlő területű négyszög szerkesztésének klasszikusnak mondható, euklideszi lehetősége foglalkoztatta, amely -ha visszaemlékszünk iskolai tanulmányainkból-, körzővel és vonalzóval történik. Ma már tudjuk, hogy ez a probléma euklideszi szerkesztési elvek alapján nem megoldható.

 

Programozási szempontból a kör négyszögesítése azt az implementációs feladatot dobhatja fel számunkra, miszerint létezik-e azonos területű kör és négyszög?

 

A matematikában alapszinten jártasak is láthatják a legelső problémát: a körszámításokhoz elengedhetetlenül szükséges PI értéke végtelen, ráadásul nem ismétlődik periodikusan.

 

www.informatika-programozas.hu - Ezt most meg kell tanulni!

 

Ebből nem jön ki semmi jó, ha kört egy másik, jóval egzaktabb síkidommal hasonlítunk össze, ezért a számítások csakis közelítőek lehetnek. Már csak az a kérdés, hogy mennyire lesznek azok.

 

Ezt szándékosan mi is erőltethetjük, ha double lebegőpontos pontosság helyett float adattípusra váltunk, ezáltal szűkítjük az eredménypontosságot, remélve, hogy ezzel lesz használható végeredményünk.

 

A síkidomok területszámító alapképletei a következők, ezt párhuzamosan Java-közeli képlettel is megadhatjuk:

Könnyű belátni a következőt:

ha kör sugarát 1 egységnek vesszük, akkor 1 egység sugarú kör területe kisebb a köré írt négyzet területénél, ekkor a = 2r...

 

www.informatika-programozas.hu - A kör négyszögesítése

 

...√2 egység sugarú kör területe viszont már nagyobb a beleírt négyzet területénél:

 

www.informatika-programozas.hu - A kör négyszögesítése

 

Következésképpen a keresett a négyzet-oldalhossz kevéssel 2 alatt lehet. Ezt erősítik a további, négyzettel kapcsolatos képletek:

Az algoritmus egyszerre 2 irányban fog haladni:

Az első végrehajtási mód for ciklus lehet, amelynek léptetését jó nagyra állítjuk. Ha a területek között van egyezés, a ciklusok megállhatnak, sőt abban az esetben is, ha nem volt egyezés, de a körterület már nagyobb négyzetterületnél, hiszen ekkor már nincs értelme a ciklus folytatásának.

 

Érdekes deklaráció a 3.14f. Magát a 3.14 (mint literált) Java úr alapértelmezésben nem fogja elfogadni, ezért egy f szimbólummal jeleznünk kell számára, hogy lebegőpontos számra gondolunk.

 

Nézzük meg a futtatható Java-kódot:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

public class Main {
public static void main(String[] args) {
    float r = 1;
    float a = 2;
    float területKor = 0;
    float területNegyzet = 0;

    for(int i = 1; i <= 100; i++){
        területKor = (r * r) * 3.14f;

        System.out.println(r + " sugár esetén a körterület: " + területKor);
        r += 0.001;

        területNegyzet = a * a;
        System.out.println(a + " oldalhossz esetén a négyzetterület: " + területNegyzet);
        a -= 0.001;


        System.out.println();

        if(területKor == területNegyzet){
            System.out.println("Egyezés " + területNegyzet + " esetén!");
            break;
        }

        else if(területKor > területNegyzet){
            System.out.println("Nincs egyezés!");
            break;
            }
        }
    }
}

 

Végeredmény:
1.0 sugár esetén a körterület: 3.14
2.0 oldalhossz esetén a négyzetterület: 4.0

1.001 sugár esetén a körterület: 3.1462834
1.999 oldalhossz esetén a négyzetterület: 3.9960008

1.0020001 sugár esetén a körterület: 3.1525733
1.9979999 oldalhossz esetén a négyzetterület: 3.9920037

1.0030001 sugár esetén a körterület: 3.1588695
1.9969999 oldalhossz esetén a négyzetterület: 3.9880085

1.0040002 sugár esetén a körterület: 3.1651714
1.9959998 oldalhossz esetén a négyzetterület: 3.9840152

1.0050002 sugár esetén a körterület: 3.1714802
1.9949998 oldalhossz esetén a négyzetterület: 3.980024

1.0060003 sugár esetén a körterület: 3.177795
1.9939997 oldalhossz esetén a négyzetterület: 3.9760349

1.0070003 sugár esetén a körterület: 3.184116
1.9929997 oldalhossz esetén a négyzetterület: 3.9720478

1.0080004 sugár esetén a körterület: 3.1904435
1.9919996 oldalhossz esetén a négyzetterület: 3.9680624

1.0090004 sugár esetén a körterület: 3.1967773
1.9909996 oldalhossz esetén a négyzetterület: 3.9640794

1.0100005 sugár esetén a körterület: 3.2031171
1.9899995 oldalhossz esetén a négyzetterület: 3.960098

1.0110005 sugár esetén a körterület: 3.2094634
1.9889995 oldalhossz esetén a négyzetterület: 3.956119

1.0120006 sugár esetén a körterület: 3.2158158
1.9879994 oldalhossz esetén a négyzetterület: 3.9521418

1.0130006 sugár esetén a körterület: 3.2221746
1.9869994 oldalhossz esetén a négyzetterület: 3.9481666

1.0140007 sugár esetén a körterület: 3.2285397
1.9859993 oldalhossz esetén a négyzetterület: 3.9441934

1.0150007 sugár esetén a körterület: 3.2349112
1.9849993 oldalhossz esetén a négyzetterület: 3.9402223

1.0160007 sugár esetén a körterület: 3.241289
1.9839993 oldalhossz esetén a négyzetterület: 3.936253

1.0170008 sugár esetén a körterület: 3.2476728
1.9829992 oldalhossz esetén a négyzetterület: 3.9322858

1.0180008 sugár esetén a körterület: 3.254063
1.9819992 oldalhossz esetén a négyzetterület: 3.9283206

1.0190009 sugár esetén a körterület: 3.2604594
1.9809991 oldalhossz esetén a négyzetterület: 3.9243574

1.0200009 sugár esetén a körterület: 3.2668622
1.9799991 oldalhossz esetén a négyzetterület: 3.9203963

1.021001 sugár esetén a körterület: 3.2732713
1.978999 oldalhossz esetén a négyzetterület: 3.9164371

1.022001 sugár esetén a körterület: 3.2796862
1.977999 oldalhossz esetén a négyzetterület: 3.9124799

1.0230011 sugár esetén a körterület: 3.286108
1.9769989 oldalhossz esetén a négyzetterület: 3.9085248

1.0240011 sugár esetén a körterület: 3.2925358
1.9759989 oldalhossz esetén a négyzetterület: 3.9045715

1.0250012 sugár esetén a körterület: 3.29897
1.9749988 oldalhossz esetén a négyzetterület: 3.9006205

1.0260012 sugár esetén a körterület: 3.3054104
1.9739988 oldalhossz esetén a négyzetterület: 3.8966713

1.0270013 sugár esetén a körterület: 3.3118575
1.9729987 oldalhossz esetén a négyzetterület: 3.892724

1.0280013 sugár esetén a körterület: 3.3183103
1.9719987 oldalhossz esetén a négyzetterület: 3.888779

1.0290014 sugár esetén a körterület: 3.3247695
1.9709986 oldalhossz esetén a négyzetterület: 3.8848357

1.0300014 sugár esetén a körterület: 3.331235
1.9699986 oldalhossz esetén a négyzetterület: 3.8808944

1.0310014 sugár esetén a körterület: 3.337707
1.9689986 oldalhossz esetén a négyzetterület: 3.8769553

1.0320015 sugár esetén a körterület: 3.3441854
1.9679985 oldalhossz esetén a négyzetterület: 3.873018

1.0330015 sugár esetén a körterület: 3.3506696
1.9669985 oldalhossz esetén a négyzetterület: 3.869083

1.0340016 sugár esetén a körterület: 3.3571603
1.9659984 oldalhossz esetén a négyzetterület: 3.8651497

1.0350016 sugár esetén a körterület: 3.3636572
1.9649984 oldalhossz esetén a négyzetterület: 3.8612187

1.0360017 sugár esetén a körterület: 3.3701606
1.9639983 oldalhossz esetén a négyzetterület: 3.8572893

1.0370017 sugár esetén a körterület: 3.3766701
1.9629983 oldalhossz esetén a négyzetterület: 3.8533623

1.0380018 sugár esetén a körterület: 3.3831856
1.9619982 oldalhossz esetén a négyzetterület: 3.849437

1.0390018 sugár esetén a körterület: 3.3897078
1.9609982 oldalhossz esetén a négyzetterület: 3.8455138

1.0400019 sugár esetén a körterület: 3.3962364
1.9599981 oldalhossz esetén a négyzetterület: 3.8415928

1.0410019 sugár esetén a körterület: 3.4027712
1.9589981 oldalhossz esetén a négyzetterület: 3.8376734

1.042002 sugár esetén a körterület: 3.409312
1.957998 oldalhossz esetén a négyzetterület: 3.8337562

1.043002 sugár esetén a körterület: 3.4158592
1.956998 oldalhossz esetén a négyzetterület: 3.8298411

1.044002 sugár esetén a körterület: 3.4224126
1.955998 oldalhossz esetén a négyzetterület: 3.825928

1.0450021 sugár esetén a körterület: 3.4289725
1.9549979 oldalhossz esetén a négyzetterület: 3.8220167

1.0460021 sugár esetén a körterület: 3.4355385
1.9539979 oldalhossz esetén a négyzetterület: 3.8181076

1.0470022 sugár esetén a körterület: 3.4421108
1.9529978 oldalhossz esetén a négyzetterület: 3.8142004

1.0480022 sugár esetén a körterület: 3.4486895
1.9519978 oldalhossz esetén a négyzetterület: 3.8102953

1.0490023 sugár esetén a körterület: 3.4552743
1.9509977 oldalhossz esetén a négyzetterület: 3.806392

1.0500023 sugár esetén a körterület: 3.4618654
1.9499977 oldalhossz esetén a négyzetterület: 3.802491

1.0510024 sugár esetén a körterület: 3.468463
1.9489976 oldalhossz esetén a négyzetterület: 3.7985916

1.0520024 sugár esetén a körterület: 3.4750667
1.9479976 oldalhossz esetén a négyzetterület: 3.7946944

1.0530025 sugár esetén a körterület: 3.4816768
1.9469975 oldalhossz esetén a négyzetterület: 3.7907994

1.0540025 sugár esetén a körterület: 3.488293
1.9459975 oldalhossz esetén a négyzetterület: 3.7869062

1.0550026 sugár esetén a körterület: 3.4949157
1.9449974 oldalhossz esetén a négyzetterület: 3.783015

1.0560026 sugár esetén a körterület: 3.5015445
1.9439974 oldalhossz esetén a négyzetterület: 3.779126

1.0570027 sugár esetén a körterület: 3.5081797
1.9429973 oldalhossz esetén a négyzetterület: 3.7752388

1.0580027 sugár esetén a körterület: 3.514821
1.9419973 oldalhossz esetén a négyzetterület: 3.7713535

1.0590028 sugár esetén a körterület: 3.5214686
1.9409972 oldalhossz esetén a négyzetterület: 3.7674704

1.0600028 sugár esetén a körterület: 3.528123
1.9399972 oldalhossz esetén a négyzetterület: 3.7635891

1.0610029 sugár esetén a körterület: 3.5347831
1.9389971 oldalhossz esetén a négyzetterület: 3.7597098

1.0620029 sugár esetén a körterület: 3.5414498
1.9379971 oldalhossz esetén a négyzetterület: 3.7558327

1.063003 sugár esetén a körterület: 3.5481222
1.936997 oldalhossz esetén a négyzetterület: 3.7519577

1.064003 sugár esetén a körterület: 3.5548015
1.935997 oldalhossz esetén a négyzetterület: 3.7480843

1.065003 sugár esetén a körterület: 3.561487
1.934997 oldalhossz esetén a négyzetterület: 3.7442133

1.0660031 sugár esetén a körterület: 3.5681784
1.9339969 oldalhossz esetén a négyzetterület: 3.740344

1.0670031 sugár esetén a körterület: 3.5748765
1.9329969 oldalhossz esetén a négyzetterület: 3.736477

1.0680032 sugár esetén a körterület: 3.5815809
1.9319968 oldalhossz esetén a négyzetterület: 3.7326117

1.0690032 sugár esetén a körterület: 3.5882914
1.9309968 oldalhossz esetén a négyzetterület: 3.7287486

1.0700033 sugár esetén a körterület: 3.5950081
1.9299967 oldalhossz esetén a négyzetterület: 3.7248874

1.0710033 sugár esetén a körterület: 3.6017313
1.9289967 oldalhossz esetén a négyzetterület: 3.721028

1.0720034 sugár esetén a körterület: 3.6084607
1.9279966 oldalhossz esetén a négyzetterület: 3.717171

1.0730034 sugár esetén a körterület: 3.6151962
1.9269966 oldalhossz esetén a négyzetterület: 3.713316

1.0740035 sugár esetén a körterület: 3.621938
1.9259965 oldalhossz esetén a négyzetterület: 3.7094626

1.0750035 sugár esetén a körterület: 3.6286862
1.9249965 oldalhossz esetén a négyzetterület: 3.7056115

1.0760036 sugár esetén a körterület: 3.6354408
1.9239964 oldalhossz esetén a négyzetterület: 3.7017624

1.0770036 sugár esetén a körterület: 3.6422017
1.9229964 oldalhossz esetén a négyzetterület: 3.697915

1.0780036 sugár esetén a körterület: 3.6489685
1.9219964 oldalhossz esetén a négyzetterület: 3.69407

1.0790037 sugár esetén a körterület: 3.6557417
1.9209963 oldalhossz esetén a négyzetterület: 3.6902268

1.0800037 sugár esetén a körterület: 3.6625214
1.9199963 oldalhossz esetén a négyzetterület: 3.6863856

1.0810038 sugár esetén a körterület: 3.6693075
1.9189962 oldalhossz esetén a négyzetterület: 3.6825464

1.0820038 sugár esetén a körterület: 3.6760993
1.9179962 oldalhossz esetén a négyzetterület: 3.6787093

1.0830039 sugár esetén a körterület: 3.682898
1.9169961 oldalhossz esetén a négyzetterület: 3.674874

Nincs egyezés!

 

Ha nem kívánjuk látni a felesleges információkat, ki kell vennünk a köztes System.out.println() metódusokat:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

public class Main {
public static void main(String[] args) {
    float r = 1;
    float a = 2;
    float területKor = 0;
    float területNegyzet = 0;

    for(int i = 1; i <= 100; i++){
        területKor = (r * r) * 3.14f;

        r += 0.001;

        területNegyzet = a * a;
        a -= 0.001;


        if(területKor == területNegyzet){
            System.out.println("Egyezés " + területNegyzet + " esetén!");
            break;
        }

        else if(területKor > területNegyzet){
            System.out.println("Nincs egyezés!");
            break;
            }
        }
    }
}

 

Végeredmény:

Nincs egyezés!

 

Természetesen a ciklusfuttatás más módon, például hátultesztelő ciklussal is elvégezhető. Ebben az esetben azonban le kell kezelnünk a Nincs egyezés! kiírását, legegyszerűbben ezt egy boolean típusú változó (egyezes) segítségével tudjuk szabályozni és megtenni:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

public class Main {
public static void main(String[] args) {
    float r = 1;
    float a = 2;
    float területKor = 0;
    float területNegyzet = 0;
    boolean egyezes;

    do{
        egyezes = false;
        területKor = (r * r) * 3.14f;
        r += 0.001;
        területNegyzet = a * a;
        a -= 0.001;

        if(területKor == területNegyzet){
            System.out.println("Egyezés " + területNegyzet + " esetén!");
            egyezes = true;
            break;
        }
    }while(területKor < területNegyzet);
    if(egyezes == false){
        System.out.println("Nincs Egyezés!");
        }
    }
}

 

Végeredmény:

Nincs egyezés!

 

Az előző eredmény lista utolsó sorai pillantva megállapíthatjuk...

 

...


1.0810038 sugár esetén a körterület: 3.6625214
1.9199963 oldalhossz esetén a négyzetterület: 3.6863856

1.0820038 sugár esetén a körterület: 3.6693075
1.9189962 oldalhossz esetén a négyzetterület: 3.6825464

1.0830039 sugár esetén a körterület: 3.6760993
1.9179962 oldalhossz esetén a négyzetterület: 3.6787093

1.0840039 sugár esetén a körterület: 3.682898
1.9169961 oldalhossz esetén a négyzetterület: 3.674874
 

. hogy amint az várható volt, még szűkító float adattípus esetén sincs egyezés. Számunkra az utolsó előtti sorpáros a legfontosabb, hiszen itt közelítenek egymáshoz legjobban az eredmények, voltaképpen századpontosságig egyeznek:

 

1.0830039 sugár esetén a körterület: 3.6760993
1.9179962 oldalhossz esetén a négyzetterület: 3.6787093

 

Ezek után már csak azt kell tisztáznunk, hogy van-e a Java-rendszerben olyan metódus, amelyik képes kellő mértékben redukálni az éterben lebegő pontosságot?

 

Az Interneten rákeresve természetesen több metódus is rendelkezésünkre áll. Az egyik nagyon döcögős, voltaképpen a lebegőpontos számból String formátumot gyárt és jó hentes módjára azt vagdossa össze kellő mennyiség szerint:

 

Forrás - Source: www.stackoverflow.com

 

public static float onlyTwoDecimalPlaces(String number) {
    StringBuilder sbFloat = new StringBuilder(number);
    int start = sbFloat.indexOf(".");
    if (start < 0) {
        return new Float(sbFloat.toString());
    }
    int end = start+3;
    if((end)>(sbFloat.length()-1)) end = sbFloat.length();
        String twoPlaces = sbFloat.substring(start, end);
        sbFloat.replace(start, sbFloat.length(), twoPlaces);
        return new Float(sbFloat.toString());
    }

 

A másik, jóval letisztultabb kóddal sok helyen találkoztam:

 

float myFloat = 12.349;
myFloat = (float)((int)( myFloat *100f ))/100f
;

 

...és alapműködése miatt nagyon egyszerűen illeszthető a jelen fejezet kódjaiba:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

public class Main {
public static void main(String[] args) {
    float r = 1;
    float a = 2;
    float területKor = 0;
    float területNegyzet = 0;

    for(int i = 1; i <= 100; i++){
        területKor = (r * r) * 3.14f;

        területKor = (float)((int)(területKor * 100f )) / 100f;
        r += 0.001;


        területNegyzet = a * a;

        területNegyzet = (float)((int)(területNegyzet * 100f )) / 100f;
        System.out.println(a + " oldalhossz esetén a négyzetterület: " + területNegyzet);
        a -= 0.001;

        if(területKor == területNegyzet){
            System.out.println("Egyezés " + területNegyzet + " esetén!");
            break;
        }

        else if(területKor > területNegyzet){
            System.out.println("Nincs egyezés!");
            break;
            }
        }
    }
}

 

Végeredmény:

Egyezés 3.67 esetén!

 

Nézzünk meg a kerekítésre egy másik metódust is:

 

double d = 16.66667;
DecimalFormat decimalFormat= new DecimalFormat("#.##");
decimalFormat.setRoundingMode(RoundingMode.FLOOR);
System.out.println("Eredmény: " + decimalFormat.format(d));

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.math.RoundingMode;
import java.text.DecimalFormat;

public class Main {
public static void main(String[] args) {
    double d = 16.66667;
    DecimalFormat decimalFormat= new DecimalFormat("#.##");
    decimalFormat.setRoundingMode(RoundingMode.FLOOR);
    System.out.println("Eredmény: " + decimalFormat.format(d));
    }
}

 

Végeredmény:

Eredmény: 16,66

 

Ekkor azonban már a double típusokból kapott String értékeket hasonlítjuk össze (if(sztringTeruletKor.equals(sztringTeruletNegyzet)):

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.math.*;
import java.text.DecimalFormat;

 

public class Main {
public static void main(String[] args) {
    float r = 1;
    float a = 2;
    double területKor = 0;
    double területNegyzet = 0;

    for(int i = 1; i <= 100; i++){
        DecimalFormat decimalFormat = new DecimalFormat("#.##");
        decimalFormat.setRoundingMode(RoundingMode.FLOOR);
        területKor = (r * r) * Math.PI;
        String sztringTeruletKor = decimalFormat.format(területKor);
        r += 0.001;

        területNegyzet = a * a;
        String sztringTeruletNegyzet = decimalFormat.format(területNegyzet);
        a -= 0.001;

        if(sztringTeruletKor.equals(sztringTeruletNegyzet)){
            System.out.println("Egyezés " + sztringTeruletNegyzet + " esetén!");
            break;
        }

    else if(területKor > területNegyzet){
        System.out.println("Nincs egyezés!");
        break;
        }
    }
    }
}

 

Végeredmény:

Egyezés 3.67 esetén!

 

www.informatika-programozas.hu - Ezt most meg kell tanulni!

 

Mindettől függetlenül most már kijelenthetjük gyanúnkat, miszerint matematikailag nézve területek szempontjából nem lehetséges a kör négyszögesítése. A fenti kódok pusztán programozás-technikailag voltak érdekesek.

 

Ugyanakkor a kerekítő egyezések során kaptunk egy közelítő 1.9179962 négyzetoldalhosszt is. A területszámító képletek rendezésével...

 

a2 = r2 * PI

a = r * √PI

 

...leellenőrizhetjük ezen értéket. 1.0830039 sugár esetén a négyzetoldalhossz megközelítőleg szintén 1.91 körüli lesz.

 

www.informatika-programozas.hu - Házi feladat

 

Házi feladat - Írjuk át a fenti kódot double adattípusra és használjuk fel a Math osztály adatait, metódusait! Változni fog-e a végeredmény?

 

A megoldás fejezete a képre kattintva érhető el.