( lacos | 2024. 11. 20., sze – 22:03 )

Ilyen eset (c-1)(c-2)/2 van [...], a legnagyobb az A=c-2, B=1, n=(c-1)^2

Továbbmorfondíroztam ezen -- ez a módszer nemcsak jó, hanem nagyszerű :) Ugyanis ha az első (n, c) inputra r<=0 jön ki (vagyis az utolsó oszlop kiürül), akkor tudsz elégséges követelményt megfogalmazni a c-re úgy, hogy második nekifutásra a módszer biztosan működjön: (√n)+1>c. Be tudsz állítani egy olyan új c-t, amire a módszer működni fog.

  • Ha n négyzetszám, akkor √n egész, így c := √n megfelel.
  • Ha n nem négyzetszám, akkor c := (⌊√n⌋+1) a legszorosabban értelmezett jó érték. (Lássuk azt, hogy ha n négyzetszám, akkor ez a számítás nem felel meg c-hez!)

A fentieket együttesen úgy is kifejezhetjük, hogy c :=⌈√n⌉.

Itt az az érdekes, hogy C-ben hogyan kódolod ezt le. Nekem az egyesített, felső egészrészes forma (c := ⌈√n⌉) nem tetszik, mert a c-r felső korlát van, tehát ha a ceil(sqrt(n))-ben mind az sqrt, mint a ceil felfelé kerekít, abból baj lehet. (Pl. n négyzetszám, de sqrt(n) egy olyan lebegőpontos értéket ad, ami a matematikai, egész értékű négyzetgyöknél epszilonnal nagyobb, amit aztán a ceil felkerekít a következő egészre.) Úgyhogy a szétválasztott esetek jobban tetszenek. Ott viszont:

Egyrészt hogyan tudjuk biztonsággal (egzaktul) megnézni, hogy n négyzetszám-e?

Másrészt sqrt()-hez a lebegőpontos környezetet úgy kell beállítani, hogy nulla (vagy mínusz végtelen) felé kerekítsen, attól függetlenül, hogy utána az eredményre a floor()-t alkalmaznánk. (Elvileg nem tartom lehetetlennek, hogy alapból felfelé kerekítő floating point env-nél az sqrt(n) egész számot adna olyan n-re, amely n=(k^2)-1 valamely egész k-ra. És akkor a floor(sqrt(n)) eggyel nagyobb értéket adna (nevesül floor(k)==k-t), mint a matematikai ⌊√n⌋ (ami k-1 lenne), vagyis a "c=floor(sqrt(n))+1" értékadás megszegné a c-re vonatkozó követelményt.)

Őszintén szólva nincs jobb ötletem, mint valahol feltúrni egy integer sqrt módszert (vagy "szegényemberes" megoldással megcsinálni lineáris vagy logaritmikus kereséssel), amely pont az ⌊√n⌋ értéket találja meg, utána pedig visszafelé ellenőrizni (egész aritmetikával), hogy ⌊√n⌋*⌊√n⌋ == n. Ha igen, akkor n négyzetszám (és c:=⌊√n⌋=√n), egyébként c nem négyzetszám (és c:=⌊√n⌋+1).