Factorial
դասը և նրա համար սահմանել main
ստատիկ մեթոդը, հայտարարել ամբողջաթիվ (int
) փոփոխականներ ու նրանց վերագրել արժեքներ, կազմակերպել կրկնություն (while
) և արտածել հաշվարկման արդյունքները (System.out.println()
)։ Այդ ծրագրի օրինակով ցուցադրվեց նաև թե ինչպես թարգմանել Java լեզվով գրված կոդն ու կատարել վիրտուալ մեքենայի օգնությամբ։Բայց խնդրի լուծման տեսակետից բերված ծրագիրն ուներ մի քանի թերություններ։ Թվարկեմ դրանք և փորձեմ առաջարկել լուծումներ։
int
տիպը Java լեզվում ուն 32 բիթ երկարություն և, քանի որ ֆակտորիալը արագ աճող ֆունկցիա է, նրանում կարելի է հաշվել 1-ից 12 թվերի ֆակտորիալները։ Լուծում կարող էր հանդիսանալ 64 բիթ երկարությամբlong
տիպը, բայց նրանով էլ կարելի է հաշվել միայն 1-ից 20 թվերի ֆակտորիալները։- Ծրագիրը գրված է միայն 12 թվի ֆակտորիալը հաշվելու համար։ Այն հնարավորություն չունի օգտագործողից հարցնելու թիվը նրա ֆակտորիալը հաշվելու համար։
- Ֆակտորիալի հաշվարկը կատարվում է
main
մեթոդի մարմնում։ Ավելի հարմար կլիներ սահմանել մի ֆունկցիա, որն արգումենտում ստանում է դրական ամբողջ թիվ և վերադարձնում է նրա ֆակտորիալը։
java.math
փաթեթում։ Այդ փաթեթի BigInteger
դասով իրականացված են անսահմանափակ երկարությամբ ամբողջ թվերը։ Այդ դասը մեր ծրագրում մատչելի դարձնելու համար Factorial
դասի սահմանումից առաջ պետք է գրել.
import java.math.BigInteger;Սա ցույց է տալիս, որ ծրագրում կարող ենք հայտարարել և օգտագործել
BigInteger
դասի նմուշներ։BigInteger
դասն ունի մի քանի կոնստրուկտորներ, որոնք ստեղծում և արժեքավորում են օբյեկտը, բայց դրանցից մեզ հետաքրքրելու է միայն BigInteger(String val)
տարբերակը, որը օբյեկտն արժեքավորում է թվի տեքստային ներկայացմամբ։ Օրինակ, 123456789012345678901234567890 արժեքով BigInteger
օբյեկտ ստեղծելու համար պետք է գրել.
BigInteger num1 = new BigInteger("123456789012345678901234567890");Բացի Java լեզվի բազային տիպերով ներկայացվող օբյեկտներից, իսկ դրանք են
byte
(մեկ բայթ), short
(կարճ ամբողջ թիվ, 16 բիթ), int
(ամբողջ թիվ, 32 բիթ), long
(երկար ամբողջ թիվ, 64 բիթ), float
(սահող կետով թիվ, 32 բիթ), double
(կրկնակի ճշտության իրական թիվ, 64 բիթ), boolean
(տրամաբանական) և char
(նիշ), բոլոր մյուս օբյեկտները կառուցվում են new
գործողության օգտագործմամբ։ BigInteger num1;
արտահայտությամբ պարզապես հայտարարվում է հղում BigInteger
տիպի օբյեկտին, իսկ օբյեկտը կառուցվում է new BigInteger("1234...");
արտահայտությամբ։Ֆակտորիալի հաշվարկման համար պետք է հայտարարել երկու
BigInteger
օբյեկտ. prod
, որը պետք է ունենա 1 նախնական արժեքը, և n
, որի ֆակտորիալը պետք է հաշվել։ Այս անգամ n
-ի սկսզբնական արժեք ընդունենք 200 թիվը.
BigInteger prod = BigInteger.ONE; BigInteger n = new BigInteger("200");
BigInteger
դասում հայտարարված է 1 թվային արժեքով ONE
հաստատունը, որն օգտագործված է որպես prod
փոփոխականի նախնական արժեք։ Նույն դասում սահմանված են նաև ZERO
և TEN
հաստատունները՝ համապատասխանաբար 0 և 10 թվային արժեքներով։Հաշվարկների համար մեզ հարկավոր են բազմապատկման և հանման գործողությունները։
BigInteger
դասի multiply մեթոդը կատարում է երկու BigInteger
-ների բազմապատկում, իսկ subtract մեթոդը BigInteger
թվից հանում է մի ուիշը։ compareTo մեթոդն էլ համեմատում է երկու BigInteger
օբյեկտներ և վերադարձնում է -1, 0, 1, երբ առաջին թիվը համապատասխանաբար փոքր է, հավասար է կամ մեծ է երկրորդից։Այս ամենը հաշվի առնելով արդեն կարող ենք մեր հին ծրագրի ցիկլը ձևափոխել և գրել ահա այսպես.
while( n.compareTo(BigInteger.ZERO) == 1 ) { prod = prod.multiply(n); n = n.subtract(BigInteger.ONE); }
System
դասի in
դաշտի read
մեթոդը հնարավորություն է տալիս ստեղնաշարից (ստանդարտ ներածման հոսքից) ներմուծել բայթերի զանգված՝ byte[]
։ Օրինակ, գրենք կոդի մի հատված, որը ներածման հոսքից կարդում է բայթերի զանգված, այն վերածում է տողի, ապա արտածում է ստանդարտ արտածման հոսքի վրա։
Նախ հայտարարենք
buffer
անունով բայթերի զանգված, օրինակ, 20 երկարությամբ, որի մեջ պետք է կարդալ ներածված տողը։
byte[] buffer = new byte[20];Ապա կանչենք
read
մեթոդը և նրա արգումենտում տանք buffer
զանգվածը։ Կատարվելուց հետո buffer
-ը կպարունակի ներածման հոսքից տրված տվյալները (ինչպես նաև ներածման ավարտին տրված նոր տողի սիմվոլը)։
System.in.read(buffer);Այնուհետև
String
դասի կոնստրուկտորով բայթերի զանգվածից կառուցենք տեքստային ներտայացումը։
String str = new String(buffer);Եվ վերջապես, արտածենք տեքստային ներկայացումը՝ նախապես
trim
մեթոդով նրա աջ ու ձախ կողմերից հեռացնելով բացատանիշերը։
System.out.println(str.trim());Այսպիսով, ֆակտորիալի հաշվարկման մեր ծրագրում
n
փոփոխականին արժեք վերագրող «BigInteger n = new BigInteger("200");
» տողը փոխարինենք հետևյալ հատվածով․
byte[] buffer = new byte[32]; System.in.read(buffer); String str = new String(buffer); BigInteger n = new BigInteger(str.trim());Եվ, ի մի բերելով ամբողջ ասվածը, կունենանք ամբողջական ծրագրի հետևյալ տեսքը․
package factorial; import java.math.BigInteger; public class Factorial { public static void main(String[] args) { byte[] buffer = new byte[32]; System.in.read(buffer); String str = new String(buffer); BigInteger n = new BigInteger(str.trim()); BigInteger res = BigInteger.ONE; while( n.compareTo(BigInteger.ZERO) > 0 ) { res = res.multiply(n); n = n.subtract(BigInteger.ONE); } System.out.println(res); } }Երբ փոձենք «
javac -d . Factorial.java
» հրամանով թարգմանել ծրագիրը, ապա Java լեզվի կոմպիլյատորը կարտածի սխալի հաղորդագրություն՝ ահա այս տեսքով․
Factorial.java:9: unreported exception java.io.IOException; must be caught or declared to be thrown System.in.read(buffer); ^ 1 errorԲանն այն է, որ
read
մեթոդը գեներացնում է IOException
տիպի բացառություն։ Եվ կոմպիլյատորը պահանջում է կա՛մ որսալ ու մաշկել այդ բացառությունը, կա՛մ հայտարարել, որ main
մեթոդում գեներացվում են բացառություններ։ Առայժմ հետաձգենք բացառությունների մշակումը, բայց main
մեթոդի վերնագիրը ձևափոխենք այնպես, որ երևա նրանում գեներացված բացառության տիպը․
public static void main(String[] args) throws IOException { ... }Իհարկե, քանի որ
java.io.IOException
դասը սահմանված է java.io
փաթեթում, Factorial
դասի սահմանումից առաջ պետք է ներմուծել այն։
import java.io.IOException;
Factorial
դասի երկու նոր ստատիկ մեթոդներ, որոնցից առաջինը օգտագործողից պահանջում է ներածել թիվ և վերադարձնում է այդ թվի BigInteger
ներկայացումը։ Իսկ երկրորդը արգումենտում ստանում է BigInteger
թիվ և վերադարձնում է նրա ֆակտորիալը նորից BigInteger
տեսքով։
Առաջին մեթոդի սահմանումը շատ պարզ է և ունի հետևյալ տեսքը․
private static BigInteger inputNumber() throws IOException { byte[] buffer = new byte[32]; System.in.read(buffer); String str = new String(buffer); return new BigInteger(str.trim()); }
private
ծառայողական բառով սահմանված մեթոդները (ինչպես նաև դասերը, դաշտերը և այլն) տեսանելի են միայն դասի սահմանման մեջ։ Այս inputNuber
մեթոդն օգտագործվելու է միայն main
մեթոդում, և նրա տեսանելիության տիրույթը սահմանափակված է private
բառով։
Նշեցինք, որ ֆակտորիալը հաշվող ֆունկցիան ստանում է
BigInteger
թիվը և վերադարձնում է նրա ֆակտորիալը՝ ներից BigInteger
տեսքով։ Սահմանենք factorial
ստատիկ մեթոդը, բայց այս անգամ կրկնման հրամանի փոխարեն օգտագործենք ռեկուրսիա։ (N=0, ապա N!=1, հակառակ դեպքում՝ N!=N * (N-1)!)։
private static BigInteger factorial(BigInteger num) { if( 0 == num.compareTo(BigInteger.ZERO) ) return BigInteger.ONE; return num.multiply(factorial(num.subtract(BigInteger.ONE))); }Քանի որ
BigInteger
օբյեկտները չփոփոխվող են (immutable), multiply
(բազմապատկում) և subtract
(հանում) մեթոդները ստեղծում և վերադարձնում են համապատասխան նոր օբյեկտը։
package factorial; import java.io.IOException; import java.math.BigInteger; public class Factorial { private static BigInteger inputNumber() throws IOException { byte[] buffer = new byte[32]; System.in.read(buffer); String str = new String(buffer); return new BigInteger(str.trim()); } private static BigInteger factorial(BigInteger num) { if( 0 == num.compareTo(BigInteger.ZERO) ) return BigInteger.ONE; return num.multiply(factorial(num.subtract(BigInteger.ONE))); } public static void main(String[] args) throws IOException { BigInteger n = inputNumber(); BigInteger res = factorial(n); System.out.println(res); } }Թարգմանենք հետևյալ հրամանով (կամ սեղմենք NetBeans միջավայրի Run կոճակը).
$ javac -d . Factorial.javaԱպա կատարենք ծրագիրը Java վիրտուալ մեքենայով, և ներածենք 1000 թիվը.
$ java factorial/Factorial 1000Ծրագրի աշխատանքի արդյունքում արտածվելու է հետևյալ բավականին մեծ արժեքը, որը կարելի է ստուգել ու համոզվել որ 1000-ի ֆակտորիալն է.
402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
No comments:
Post a Comment