import math
def safe_newton_sqrt(k, eps, guess_init=None, maxiter=10000):
if k < 0:
raise ValueError("k < 0: real square root does not exist")
if guess_init is None:
guess = k/2.0 if k != 0 else 0.5
else:
guess = guess_init
if guess == 0:
guess = 0.5
iterations = 0
for _ in range(maxiter):
dval = 2.0 * guess
if abs(dval) < 1e-16:
guess += 1e-6
dval = 2.0 * guess
val = guess*guess - k
new_guess = guess - val / dval
iterations += 1
if abs(new_guess - guess) < eps:
return {'approx': new_guess, 'iterations': iterations}
guess = new_guess
raise RuntimeError("Newton did not converge within maxiter")
def safe_bisection_sqrt(k, eps):
if k < 0:
raise ValueError("k < 0: real square root does not exist")
a = 0.0
b = max(1.0, k)
fa = a*a - k
fb = b*b - k
if fa * fb > 0:
b = max(b, 1.0)
fb = b*b - k
if fa * fb > 0:
raise ValueError("Cannot find sign change for bisection on interval [0, max(1,k)]")
iterations = 0
while (b - a)/2.0 > eps:
m = (a + b)/2.0
fm = m*m - k
iterations += 1
if fm == 0:
return {'approx': m, 'iterations': iterations}
if fa * fm < 0:
b, fb = m, fm
else:
a, fa = m, fm
return {'approx': (a+b)/2.0, 'iterations': iterations}
# 使用例
k = 24.0
eps = 1e-6
print(safe_newton_sqrt(k, eps))
print(safe_bisection_sqrt(k, eps))
aW1wb3J0IG1hdGgKCmRlZiBzYWZlX25ld3Rvbl9zcXJ0KGssIGVwcywgZ3Vlc3NfaW5pdD1Ob25lLCBtYXhpdGVyPTEwMDAwKToKICAgIGlmIGsgPCAwOgogICAgICAgIHJhaXNlIFZhbHVlRXJyb3IoImsgPCAwOiByZWFsIHNxdWFyZSByb290IGRvZXMgbm90IGV4aXN0IikKICAgIGlmIGd1ZXNzX2luaXQgaXMgTm9uZToKICAgICAgIAogICAgICAgIGd1ZXNzID0gay8yLjAgaWYgayAhPSAwIGVsc2UgMC41CiAgICBlbHNlOgogICAgICAgIGd1ZXNzID0gZ3Vlc3NfaW5pdAogICAgICAgIGlmIGd1ZXNzID09IDA6CiAgICAgICAgICAgIGd1ZXNzID0gMC41CgogICAgaXRlcmF0aW9ucyA9IDAKICAgIGZvciBfIGluIHJhbmdlKG1heGl0ZXIpOgogICAgICAgIGR2YWwgPSAyLjAgKiBndWVzcwogICAgICAgIGlmIGFicyhkdmFsKSA8IDFlLTE2OgogICAgIAogICAgICAgICAgICBndWVzcyArPSAxZS02CiAgICAgICAgICAgIGR2YWwgPSAyLjAgKiBndWVzcwogICAgICAgIHZhbCA9IGd1ZXNzKmd1ZXNzIC0gawogICAgICAgIG5ld19ndWVzcyA9IGd1ZXNzIC0gdmFsIC8gZHZhbAogICAgICAgIGl0ZXJhdGlvbnMgKz0gMQogICAgICAgIGlmIGFicyhuZXdfZ3Vlc3MgLSBndWVzcykgPCBlcHM6CiAgICAgICAgICAgIHJldHVybiB7J2FwcHJveCc6IG5ld19ndWVzcywgJ2l0ZXJhdGlvbnMnOiBpdGVyYXRpb25zfQogICAgICAgIGd1ZXNzID0gbmV3X2d1ZXNzCiAgICByYWlzZSBSdW50aW1lRXJyb3IoIk5ld3RvbiBkaWQgbm90IGNvbnZlcmdlIHdpdGhpbiBtYXhpdGVyIikKCmRlZiBzYWZlX2Jpc2VjdGlvbl9zcXJ0KGssIGVwcyk6CiAgICBpZiBrIDwgMDoKICAgICAgICByYWlzZSBWYWx1ZUVycm9yKCJrIDwgMDogcmVhbCBzcXVhcmUgcm9vdCBkb2VzIG5vdCBleGlzdCIpCiAgICBhID0gMC4wCiAgICBiID0gbWF4KDEuMCwgaykKICAgIGZhID0gYSphIC0gawogICAgZmIgPSBiKmIgLSBrCiAgICBpZiBmYSAqIGZiID4gMDoKICAgICAgCiAgICAgICAgYiA9IG1heChiLCAxLjApCiAgICAgICAgZmIgPSBiKmIgLSBrCiAgICAgICAgaWYgZmEgKiBmYiA+IDA6CiAgICAgICAgICAgIHJhaXNlIFZhbHVlRXJyb3IoIkNhbm5vdCBmaW5kIHNpZ24gY2hhbmdlIGZvciBiaXNlY3Rpb24gb24gaW50ZXJ2YWwgWzAsIG1heCgxLGspXSIpCiAgICBpdGVyYXRpb25zID0gMAogICAgd2hpbGUgKGIgLSBhKS8yLjAgPiBlcHM6CiAgICAgICAgbSA9IChhICsgYikvMi4wCiAgICAgICAgZm0gPSBtKm0gLSBrCiAgICAgICAgaXRlcmF0aW9ucyArPSAxCiAgICAgICAgaWYgZm0gPT0gMDoKICAgICAgICAgICAgcmV0dXJuIHsnYXBwcm94JzogbSwgJ2l0ZXJhdGlvbnMnOiBpdGVyYXRpb25zfQogICAgICAgIGlmIGZhICogZm0gPCAwOgogICAgICAgICAgICBiLCBmYiA9IG0sIGZtCiAgICAgICAgZWxzZToKICAgICAgICAgICAgYSwgZmEgPSBtLCBmbQogICAgcmV0dXJuIHsnYXBwcm94JzogKGErYikvMi4wLCAnaXRlcmF0aW9ucyc6IGl0ZXJhdGlvbnN9CgojIOS9v+eUqOS+iwprID0gMjQuMAplcHMgPSAxZS02CnByaW50KHNhZmVfbmV3dG9uX3NxcnQoaywgZXBzKSkKcHJpbnQoc2FmZV9iaXNlY3Rpb25fc3FydChrLCBlcHMpKQo=