Hello!REmélem tud nekem valaki segíteni!A feladat a következő lenne:
. A √x kiszámolása iterációval (c=(x-1)/4, y2+y-c=0 Ţ yi+1=c/(yi+1), ha i->végtelen, 2yi+1->gyök x) adott pontossággal (input vagy fixen beírva). Az sqrt() nem használható.
Már az is nagy segítség lenne ha valaki tuná értelmezni ezt az iterációt mert én már ezt sem nagyon értem! Vagy akármilyen más segítség jól jönne.
Köszönöm
- 3697 megtekintés
Hozzászólások
ezt nézd meg hátha:
http://www.prog.hu/tudastar/12596/Logaritmus+es+n-edik+gyok.html
illetve pár okosság még van itt is:
http://www.hik.hu/tankonyvtar/site/books/b128/
ami még eszembe jutott:
Van egy jó rekurzió a gyök(x)-re. Elég béna lesz ez így leírva. Tehát legyen:
a(0) 1, x, vagy x/2. (Vagy bármilyen pozitív szám.)
a(n+1) = (a(n)+x/a(n))/2.
Ez egy marha gyors eljárás. Ráadásul elég könnyű bizonyítani, hogy jó. Pl. x=2-re és a(0)=1 választással:
a(0)=1
a(1)=1,5
a(2)=1,416666667
a(3)=1,414215686
a(4)=1,414213562
a(5)=a(4) (!)
és gyök(2)=1,414213562. Az adatok a számológépem kijelzőjéről valók.
Mint látod, mindegy egyes iterációval egyel több helyes számjegy lesz benne.
/mazursky
- A hozzászóláshoz be kell jelentkezni
Ez a gyök sorfejtése ez jó módszer, csak mivel líneáris az egyenlet nagy pontossághoz sok számítás kell, de remekül működik.
- A hozzászóláshoz be kell jelentkezni
Hát, így nekem sem érthető, első ránézésre még erre hasonlít a legjobban.
Ezt a részt beírnád pontosabban : y2+y-c=0 Ţ.
- A hozzászóláshoz be kell jelentkezni
bocsánat nem vettem észre hogy kicsit hibásan jelent meg:
c=(x-1)/4 , yˇ2(négyzeten)+y-c=0 -> y(alsóindexbe:i+1)=c/(y(alsóindexbe:i)+1) ha i->végtelen, 2y(alsóindexbe:i)+1->gyökx
Ez már pontos. Remélem értehető is mi hol van :)
- A hozzászóláshoz be kell jelentkezni
Na kezdjük az elején. Az x szám gyökére lenne szükséged. ha x helyére beírod az adott számot akkor kapsz egy c-t ezt bevésed egy 0-ra rendezett egység együtthatós másodfokú egyenletbe. Így a másodfokú egyenlet megoldókéletébe behelyettesítve maga a szám gyoke az 2*y, ha hozzáadunk 1-et, ha jól értelmezem. Tehát itt neked csak annyi van felírva, hogy a másodfokú egyenlet megoldókélete van közelítéssel megoldva, egység együtthatóra, kivéve a c, mert az a számunk gyökét képezi. Tehát ez csak egy átrendezett másodfokú egynelet megoldóképlet közelítéssel.
- A hozzászóláshoz be kell jelentkezni
szóval hogy a én kiveszem azt akarod mondani hogy ez nem is jó a gyök megtalálására??
- A hozzászóláshoz be kell jelentkezni
Dehogynem!
Teljesen tőkéletes!
Ez egy matematikai trükk, de jó. A másodfokú egynelet megoldóképletéből van kifelyezve a c lényegében, és visszaírva. Lényegében úgy választjuk meg c-t hogy x szám gyöke legyen a megoldás. Mikorra kell neked a megoldás?
Ha ráér estére lekódolom neked C-ben.
- A hozzászóláshoz be kell jelentkezni
igazából nekem minél előbb kéne de péntekig kell leadnom. természetesenn nagyon hálás lennék ha azt nekem vlaahogy átírnád c be :)
akkor meg pláne hogyha még el is magyaráznád valamilyen úton, mert azért szeretném megérteni. Mármint c be is mert igy már kezdem kapizsgálni :D
- A hozzászóláshoz be kell jelentkezni
#include
main ()
{
double y, hiba=1.0, c, x, ry, q;
printf ("Kérem adja meg a számot:");
scanf ("%lf",&x);
c=(x-1.0)/4.0;
q=c;
while (hiba>0.0000001)
{
ry=q;
q=(c/(q+1)+q)/2;
hiba=1000.0*(ry-q);
printf ("A gyök %.15lf %lf\n",2*q+1, hiba);
};
}
//Itt a kód! Ez az első működő nem csinosítottam rajta semmit csak fut.
- A hozzászóláshoz be kell jelentkezni
Nagyon köszönöm!! Azt még megtudod mondani hogy ez a hiba>0.000001 ez azt jelenti hogy ennyi tizedes pontosan adja meg a gyököt?
- A hozzászóláshoz be kell jelentkezni
Nagyságrendileg az lenne ha nem szorozbnék rá 1000-el tahát a hiba mennek az 1/1000-e
hiba=1000.0*(ry-q);
- A hozzászóláshoz be kell jelentkezni
Bocs hogy ismét problémám van. De a tanár azt mondja hogy a hibát ugy adjam vissza hogy a q értékét(mert az a gyök) megszorozva önmagával és ezt kivonva a bekért számból. Szóval az csak annyi lenne hogy nem ezerrel szorzom vissza hanem
q val? vagy teljesen hülyeség? :D
- A hozzászóláshoz be kell jelentkezni
Ott van az a sor, hogy hiba=...., ott számolod ki a hibát. No, azt módosítsd úgy, ahogy a tanár mondja, azaz
hiba = x-(2.*q+1.)*(2.*q+1.);
- A hozzászóláshoz be kell jelentkezni
hát ha erre írom át akkor nem lesz jó még a gyök értéke sem. szóval valami nem stimmel.
- A hozzászóláshoz be kell jelentkezni
Mert a hibahatár ellenőrzését is át kell írni, hiszen tök más értékekre fog helyesen lefutni.
De ha kreatív vagy, pusztán matematikai úton is meg tudod a végén buherálni a hiba értékét úgy, hogy jól adja vissza, és akkor az eredeti kód is jó lesz. Persze ehhez picit számolni kell...
- A hozzászóláshoz be kell jelentkezni
meglett már köszönöm :D sikerült elfogadta minden ok.
köszi mégeccer mindenkinek.
- A hozzászóláshoz be kell jelentkezni
Szia(sztok)!
A hiba az ki van számolva csak azért szoroztam rá 1000-el, hogy pontosabb legyen. a számolás, de a hiba az simán a printf sorban hiba/1000-és kész.
- A hozzászóláshoz be kell jelentkezni
A programod feltételezi, hogy a hiba mindig pozitív. Lehet, hogy így van, de ezt nem egyszerű látni, azért jobb volna abszolútértéket nézni.
--
CCC3
- A hozzászóláshoz be kell jelentkezni
Írtam hogy ez az első működő, semmit nem vizsgál. pozitív számnak jó von gyököt. de igazad van ha 0-1 közötti pozitív számot választunk akkor a differenmcia negatív lesz, ezért valóban egy abs nem ártana.
- A hozzászóláshoz be kell jelentkezni
Így ránézésre nem értem, mit csinál a programod. Úgy látom, kis számokra nem valami acélos. Az enyém érintő módszerrel működik. Hasonlítsd össze a kétféle eredményt.
--
CCC3
- A hozzászóláshoz be kell jelentkezni
Azt hiszem sikerült megérteni.
Tehát a lényeg, hogy inicializálod y_0 -t valamivel, aztán folyamatosan alkalmazod az y_{i+1}= c/(y_i + 1)-et,amíg jó nem lesz. Ahol c ugye egy konstnas.
Próbáltam a módszert visszavezetni a Babiloni módszerre, de vagy én vagyok nagyon béna ma reggel, vagy tényleg nem ekvivalens a a kettő. Most el kell mennem, de ha lesz időm, ránézek megint.
szerk.: jah, és kipróbálva,szépen közelít tényleg, szóval a Babilonitól amivel eltér hibatagban az valószínűleg elhanyagolható.
- A hozzászóláshoz be kell jelentkezni
Jobb mert a hiba a számítások lépésével négyzetesen csökken. A másiknál csak líneárisan.
- A hozzászóláshoz be kell jelentkezni
Itt egy komplett Clipper program az iterációra:
// y=x**2, y --> x
function main(arg)
local y:=val(arg),y1,x1
local hiba:=1
x1:=y //első közelítés
while( abs(hiba)>0.000001 )
y1:=x1*x1
hiba:=y-y1
? x1:=(y1+hiba/2)/x1 //következő közelítés
end
A ? operátor kiírja a változót. Az x1:=(y1+hiba/2)/x1 egyenletnek fixpontja a keresett megoldás.
--
CCC3
- A hozzászóláshoz be kell jelentkezni
igazából nekem c be kéne és ebből megmondom őszintén nem sokat értek. :)
- A hozzászóláshoz be kell jelentkezni
Gondolkozol, átírod C-be.
--
CCC3
- A hozzászóláshoz be kell jelentkezni
Nem vette észre a srác, hogy működő programot kapott. Itt a C-be átírt változat:
#include <stdio.h>
#include <math.h>
int main()
{
double y,y1,x1,hiba=1;
y=20; //ennek a gyöke kell
x1=y; //első közelítés
while( fabs(hiba)>0.0000001 )
{
y1=x1*x1;
hiba=y-y1;
x1=(y1+hiba/2)/x1; //következő közelítés
printf("%f\n",x1);
}
}
--
CCC3
- A hozzászóláshoz be kell jelentkezni
Ha nem feltetlenul iteracioval szeretned megoldani, akkor ott a Taylor sor vagy a Maclaurin sor
∑f(x(0))(n)/n! * (x-x0)n
neked ez: x0=1, n meg amennyit szeretnel
0. differencial eseten: x01/2/1 * 1
1. differencial eseten: 1/2 * x0-1/2/1 * (x-x0)
2. differencial eseten: -1/4 * x0-3/2/2 * (x-x0)2
3. differencial eseten: 3/8 * x0-5/2/6 * (x-x0)3
4. differencial eseten: -15/16 * x0-7/2/24 * (x-x0)4
5. differencial eseten: 105/32 * x0-9/2/120 * (x-x0)5
...
...
...
persze ezeket osszeadod
Es neked x0=1, x meg a keresett szam!
Szerintem olyan n=15-ig ha elmesz az mar soksok tizedesjegyig pontos
- A hozzászóláshoz be kell jelentkezni
Derék dolog, de ez is iteráció.
--
CCC3
- A hozzászóláshoz be kell jelentkezni
Hat igen :-)
de ennyierovel minden az...
Egyebkent jogos amit mondasz
- A hozzászóláshoz be kell jelentkezni
Bocs, C-ben nem akarom most megírni a házidat (mert abból te semmit sem tanulsz, én meg már csináltam gyökkeresőt), csak egy kis segítség:
hogy is számolunk iterációt:
1. kiszámoljuk, amire szükségünk lesz menet közben
2. addig számolgatjuk a sorozat későbbi tagjait, amíg elég pontosak nem lettünk. Eközben persze az előző tagokat eldobhatjuk.
Tehát valami olyan, hogy
legyen c = (x-1)/4
legyen y = (valami kezdőérték, x ha nem jut jobb eszünkbe)
amígy elég pontosak nem lettünk
addig legyen y = c/(y+1)
írjuk ki gyok(x) = 2 y+1-et
Az persze jó kérdés, hogy mikor vagyunk már elég pontosak, egy lehetségés megoldás mindig eltenni y egy régebbi értékét is, és ha már a változás kisebb egy korlátnál, akkor vagyunk kész. Vagy visszahelyettesíted y-t az egyenletébe, és ha a hiba kisebb valaminél, akkor van kész.
- A hozzászóláshoz be kell jelentkezni
Már elnézést, de ha egyszer _gyorsan_ szeretnénk egész gyököt vonni, akkor a ciklusmagban lévő változóval (tehát nem 2-hatvány konstanssal) való osztás miatt a fenti algoritmusok finoman szólva szuboptimálisak. Tessék kicsit szétnézni az uclibc forrásában (int_sqrt.c):
unsigned long int_sqrt(unsigned long x)
{
unsigned long op, res, one;
op = x;
res = 0;
one = 1UL << (BITS_PER_LONG - 2);
while (one > op)
one >>= 2;
while (one != 0) {
if (op >= res + one) {
op = op - (res + one);
res = res + 2 * one;
}
res /= 2;
one /= 4;
}
return res;
}
Mint látható, csak 2-hatvánnyal való szorzás ill. osztás van benne, amit a fordító shifteléssé ill. dupla hozzáadássá fog alakítani. Amúgy csak érdekességképp, a fenti algoritmus x86 asm verziójával valamikor '95 körül találkoztam a szép emlékű comp.lang.asm.x86 newsgroupon:
From goliat.eik.bme.hu!scsing.switch.ch!swidir.switch.ch!univ-lyon1.fr!fdn.fr!uunet!cs.utexas.edu!swrinde!gatech!concert!deltacom!sean.palmer Fri Mar 31 10:08:33 1995
Path: goliat.eik.bme.hu!scsing.switch.ch!swidir.switch.ch!univ-lyon1.fr!fdn.fr!uunet!cs.utexas.edu!swrinde!gatech!concert!deltacom!sean.palmer
Distribution: world
Newsgroups: comp.lang.asm.x86
X-Apparently-to: ODD MAGNE HAAGENSEN
Subject: WANTED: square root rout
From: sean.palmer _at_ delta.com (Sean Palmer)
Message-ID: <ac.3501.8467 _at_ delta.com>
Date: Tue, 28 Mar 1995 16:12:00 -0500
Organization: deltaComm Online :: 919-481-9399 v.32bis
Lines: 37
OM>Has anyone got, or know where to find, a (fast) assembler routine for
OM>calculating the square root for 16.16 fixed point numbers? (in 386 asse
;function iSqrt(x:longint):word;
xor eax,eax
xor edx,edx
mov edi,x
mov cx,17 ;only calc 1 word, plus 1 binary point for rounding
@@L: shld edx,edi,2
shl edi,2
shl eax,1
cmp edx,eax
jle @@S
sub edx,eax
dec edx
add eax,2
@@S: dec cx
jnz @@L
shr eax,2 ;to ax, carry
adc ax,0 ;round result
xor dx,dx ;result in dx:ax
mov dl,ah
shl ax,8
ret
This should work on fixed point numbers (I just patched it in the mail
reader), provided you don't mind losing 8 bits of accuracy in the
process... There are slightly faster algorithms out there, but my at-work
copies seem to have disappeared. Unrolling the above loop would help alot.
If you wanted to save those lower 8 bits, you'd have to convert this to a
48-bit square root and shift the input up 16 bits before running it
through, which would slow it down quite a bit. 8 bit fractional accuracy is
sufficient for most applications though.
---
* WR # 380 * C program run. C program crash. C programmer drink.
- A hozzászóláshoz be kell jelentkezni