Написання власної функції квадратного кореня


74

Як ви пишете власну функцію для пошуку найточнішого квадратного кореня цілого числа?

Погуглівши, я знайшов це (заархівовано з оригінального посилання ), але по-перше, я не отримав його повністю, а по-друге, це теж приблизно.

Припустимо квадратний корінь як найближче ціле число (до фактичного кореня) або плаваюче число.


2
Ви не вказуєте, чи має результат бути цілим числом, чи може бути плаваючим.
щуп

10
Цілочисельний квадратний корінь і квадратний корінь з цілого числа - це абсолютно різні звірі.
jfs



1
Замість того, щоб звинувачувати у неможливості find where [it](http://nlindblad.org/2007/04/04/write-your-own-square-root-function/) has been movedяк кульгаве виправдання, дозвольте мені підключити веб-архів .
greybeard

Відповіді:


82

Наступне обчислює мінімум (sqrt (N)) для N> 0:

x = 2^ceil(numbits(N)/2)
loop:
    y = floor((x + floor(N/x))/2)
    if y >= x
        return x
    x = y

Це версія методу Ньютона, подана в Crandall & Pomerance, "Прості числа: обчислювальна перспектива". Причиною того, що ви повинні використовувати цю версію, є те, що люди, які знають, що вони роблять, довели, що вона сходиться точно до підлоги квадратного кореня, і це просто, тому ймовірність помилки впровадження невелика. Це також швидко (хоча можливо побудувати ще швидший алгоритм - але робити це правильно набагато складніше). Правильно реалізований двійковий пошук може бути швидшим для дуже малого N, але там ви також можете використовувати таблицю пошуку.

Щоб округлити до найближчого цілого числа, просто обчисліть t = floor (sqrt (4N)), використовуючи наведений вище алгоритм. Якщо встановлено найменший значущий біт t, тоді виберіть x = (t + 1) / 2; в іншому випадку виберіть t / 2. Зверніть увагу, що це закінчується на краватці; Ви також можете округлити вниз (або округлити до парних), подивившись, чи не є залишок ненульовим (тобто t ^ 2 == 4N).

Зверніть увагу, що вам не потрібно використовувати арифметику з плаваючою точкою. Насправді, не слід. Цей алгоритм повинен бути повністю реалізований з використанням цілих чисел (зокрема, функції floor () просто вказують на те, що слід використовувати регулярне цілочисельне ділення).


4
Метод Ньютвона був би тим шляхом, яким я пішов би. Він сходиться в квадратичній кількості ітерацій і дуже добре поводиться для більшості початкових здогадок.
ldog

7
цілочисельний квадратний корінь не є "найточнішим квадратним коренем цілого числа".
jfs

@fredrikj: ваша відповідь завжди дає ціле число . Ви припускаєте, що "найточнішим квадратним коренем цілого числа" завжди є ціле число ?
jfs

11
Очевидно, що "найточнішим квадратним коренем" є сам квадратний корінь, тому для чисельного наближення ви повинні вказати, чи потрібно вам найближче ціле число, плаваючу задану точність чи щось інше. У цьому випадку плакат запитував "найближче ціле число", яке дає вам цей алгоритм.
Фредрік Йоханссон,

2
@NairG припустимо, ви пишете число Sі Sмає Kцифри. Тоді 10^K <= S <= 10^{K+1}. Це передбачає 10^(2K) <= S**2 < 10^(2k+2). Тим не менш, якщо ви хочете знайти квадратний корінь з N, він має довжину від половини довжини Nдо числа один більше. Тож останнє є хорошою відправною точкою. Ця лінія робить це, але використовуючи 2 як основу.
enedil

38

Залежно від ваших потреб може бути використана проста стратегія «поділи і владай». Це не буде збігатися так швидко, як деякі інші методи, але новачкові може бути набагато простіше зрозуміти. Окрім того, оскільки це алгоритм O (log n) (зменшення вдвічі простору пошуку на кожній ітерації), найгіршим випадком для 32-бітового плаваючого тексту буде 32 ітерації.

Скажімо, ви хочете квадратний корінь 62.104. Ви вибираєте значення на півдорозі між 0 і цим, і додаєте його в квадрат. Якщо квадрат вище вашого числа, вам потрібно зосередитися на числах, менших за середню точку. Якщо він занадто низький, зосередьтеся на тих, хто вище.

За реальною математикою ви можете продовжувати ділити простір пошуку назавжди на дві частини (якщо він не має раціонального квадратного кореня). Насправді комп’ютери з часом закінчаться з точністю, і ви отримаєте своє наближення. Наступна програма на С ілюструє суть:

Ось кілька запусків, так що ви, сподіваємось, отримаєте уявлення про те, як це працює. Для 77:

pax> sqrt 77
Step      Number         Low        High         Mid      Square    Result
   1     77.0000      0.0000     77.0000     38.5000   1482.2500  - too high
   2     77.0000      0.0000     38.5000     19.2500    370.5625  - too high
   3     77.0000      0.0000     19.2500      9.6250     92.6406  - too high
   4     77.0000      0.0000      9.6250      4.8125     23.1602  - too low
   5     77.0000      4.8125      9.6250      7.2188     52.1104  - too low
   6     77.0000      7.2188      9.6250      8.4219     70.9280  - too low
   7     77.0000      8.4219      9.6250      9.0234     81.4224  - too high
   8     77.0000      8.4219      9.0234      8.7227     76.0847  - too low
   9     77.0000      8.7227      9.0234      8.8730     78.7310  - too high
  10     77.0000      8.7227      8.8730      8.7979     77.4022  - too high
  11     77.0000      8.7227      8.7979      8.7603     76.7421  - too low
  12     77.0000      8.7603      8.7979      8.7791     77.0718  - too high
  13     77.0000      8.7603      8.7791      8.7697     76.9068  - too low
  14     77.0000      8.7697      8.7791      8.7744     76.9893  - too low
  15     77.0000      8.7744      8.7791      8.7767     77.0305  - too high
  16     77.0000      8.7744      8.7767      8.7755     77.0099  - too high
  17     77.0000      8.7744      8.7755      8.7749     76.9996  - too low
  18     77.0000      8.7749      8.7755      8.7752     77.0047  - too high
  19     77.0000      8.7749      8.7752      8.7751     77.0022  - too high
  20     77.0000      8.7749      8.7751      8.7750     77.0009  - too high
  21     77.0000      8.7749      8.7750      8.7750     77.0002  - too high
  22     77.0000      8.7749      8.7750      8.7750     76.9999  - too low
  23     77.0000      8.7750      8.7750      8.7750     77.0000  - too low
sqrt(77.0000) = 8.7750

Для 62.104:

pax> sqrt 62.104
Step      Number         Low        High         Mid      Square    Result
   1     62.1040      0.0000     62.1040     31.0520    964.2267  - too high
   2     62.1040      0.0000     31.0520     15.5260    241.0567  - too high
   3     62.1040      0.0000     15.5260      7.7630     60.2642  - too low
   4     62.1040      7.7630     15.5260     11.6445    135.5944  - too high
   5     62.1040      7.7630     11.6445      9.7037     94.1628  - too high
   6     62.1040      7.7630      9.7037      8.7334     76.2718  - too high
   7     62.1040      7.7630      8.7334      8.2482     68.0326  - too high
   8     62.1040      7.7630      8.2482      8.0056     64.0895  - too high
   9     62.1040      7.7630      8.0056      7.8843     62.1621  - too high
  10     62.1040      7.7630      7.8843      7.8236     61.2095  - too low
  11     62.1040      7.8236      7.8843      7.8540     61.6849  - too low
  12     62.1040      7.8540      7.8843      7.8691     61.9233  - too low
  13     62.1040      7.8691      7.8843      7.8767     62.0426  - too low
  14     62.1040      7.8767      7.8843      7.8805     62.1024  - too low
  15     62.1040      7.8805      7.8843      7.8824     62.1323  - too high
  16     62.1040      7.8805      7.8824      7.8815     62.1173  - too high
  17     62.1040      7.8805      7.8815      7.8810     62.1098  - too high
  18     62.1040      7.8805      7.8810      7.8807     62.1061  - too high
  19     62.1040      7.8805      7.8807      7.8806     62.1042  - too high
  20     62.1040      7.8805      7.8806      7.8806     62.1033  - too low
  21     62.1040      7.8806      7.8806      7.8806     62.1038  - too low
  22     62.1040      7.8806      7.8806      7.8806     62.1040  - too high
  23     62.1040      7.8806      7.8806      7.8806     62.1039  - too high
sqrt(62.1040) = 7.8806

Для 49:

pax> sqrt 49
Step      Number         Low        High         Mid      Square    Result
   1     49.0000      0.0000     49.0000     24.5000    600.2500  - too high
   2     49.0000      0.0000     24.5000     12.2500    150.0625  - too high
   3     49.0000      0.0000     12.2500      6.1250     37.5156  - too low
   4     49.0000      6.1250     12.2500      9.1875     84.4102  - too high
   5     49.0000      6.1250      9.1875      7.6562     58.6182  - too high
   6     49.0000      6.1250      7.6562      6.8906     47.4807  - too low
   7     49.0000      6.8906      7.6562      7.2734     52.9029  - too high
   8     49.0000      6.8906      7.2734      7.0820     50.1552  - too high
   9     49.0000      6.8906      7.0820      6.9863     48.8088  - too low
  10     49.0000      6.9863      7.0820      7.0342     49.4797  - too high
  11     49.0000      6.9863      7.0342      7.0103     49.1437  - too high
  12     49.0000      6.9863      7.0103      6.9983     48.9761  - too low
  13     49.0000      6.9983      7.0103      7.0043     49.0598  - too high
  14     49.0000      6.9983      7.0043      7.0013     49.0179  - too high
  15     49.0000      6.9983      7.0013      6.9998     48.9970  - too low
  16     49.0000      6.9998      7.0013      7.0005     49.0075  - too high
  17     49.0000      6.9998      7.0005      7.0002     49.0022  - too high
  18     49.0000      6.9998      7.0002      7.0000     48.9996  - too low
  19     49.0000      7.0000      7.0002      7.0001     49.0009  - too high
  20     49.0000      7.0000      7.0001      7.0000     49.0003  - too high
  21     49.0000      7.0000      7.0000      7.0000     49.0000  - too low
  22     49.0000      7.0000      7.0000      7.0000     49.0001  - too high
  23     49.0000      7.0000      7.0000      7.0000     49.0000  - too high
sqrt(49.0000) = 7.0000

Це дуже повільно в порівнянні з методом Ньютона.
starblue

32
Звідси мій перший абзац - метою цієї відповіді було показати спосіб зробити це, що не вимагає розуміння числення. Звичайно, якщо ви хочете використовувати метод Ньютона всліпу (без розуміння), це нормально - це здує мій метод з води. Але я не поставив у відповіді всі ці таблиці, щоб довести швидкість - вони там навчають.
paxdiablo

4
Як метод Ньютона може бути швидшим за O (log n)? Яка часова складність методу Ньютона?
Тіто

ха-ха несвідомо, мій розум дотримується того самого алгоритму, відгадуючи квадрати десяткових чисел за допомогою калькулятора !!
Max Payne

16

Простий (але не дуже швидкий) метод для обчислення квадратного кореня з Х:

squareroot(x)
    if x<0 then Error
    a = 1
    b = x
    while (abs(a-b)>ErrorMargin) 
        a = (a+b)/2
        b = x/a
    endwhile
    return a;

Приклад: квадратний корінь (70000)

    a       b
    1   70000
35001       2
17502       4
 8753       8
 4381      16
 2199      32
 1116      63
  590     119
  355     197
  276     254
  265     264

Як бачите, він визначає верхню та нижню межі для квадратного кореня і звужує межу, поки його розмір не буде прийнятним.

Є більш ефективні методи, але цей ілюструє процес і його легко зрозуміти.

Тільки стережіться, щоб встановити Errormargin на 1, якщо, використовуючи цілі числа, у вас є нескінченний цикл.


Це найкращий алгоритм, який мені відомий для обчислення цілочисельного квадратного кореня, але я не впевнений, що режим округлення є детермінованим (схоже, він округлений до найближчого цілого числа, але я не впевнений, що це завжди так). В кінці я повертаю менші з a та b, так що функція завжди повертає floor (sqrt (x)).
Віктор Лю

Це дуже хороший і відомий алгоритм. Його ще називають чаплями або вавилонським методом. Дуже простий у реалізації! en.wikipedia.org/wiki/Babylonian_method#Babylonian_method
Tag318

Використовуючи do … while(a-b>ErrorMargin)замість цього, ви уникаєте використання функції abs () і робите це трохи швидше
Кирило

13

Дозвольте мені зазначити надзвичайно цікавий метод обчислення оберненого квадратного кореня 1 / sqrt (x), який є легендою у світі ігрового дизайну, оскільки це надзвичайно швидко. Або почекайте, прочитайте наступне повідомлення:

http://betterexplained.com/articles/understanding-quakes-fast-inverse-square-root/

PS: Я знаю, ви просто хочете квадратний корінь, але елегантність землетрусу перемогла всякий опір з мого боку :)

До речі, вищезазначена стаття також говорить про нудне десь наближення Ньютона-Рафсона.


1
Я пам’ятаю, читав про це деякий час тому. Я не гідний бути в присутності того, хто це розробив; p
Джеймс Девіс,

4
о давай ... це просто ньютон-рафсон;)
Стефано Боріні

4
Метод є Ньютона-Рафсона - тільки з допомогою наближення однієї ітерації з побитно дріб'язковий хака. Ньютон-Рафсон може обчислити багато обернених функцій, а не лише квадратний корінь.
Steve314,

4
якщо ви хочете квадратний корінь, візьміть зворотний квадратний корінь, помножте на вихідне число.
Jason S

9

Звичайно, це приблизно; саме так працює математика з числами з плаваючою комою.

У будь-якому випадку, стандартним способом є метод Ньютона . Це приблизно те саме, що використовувати серію Тейлора, інший спосіб, який відразу спадає на думку.


1
Було б чудово, якби ви запропонували у відповідь щось із точки зору реалізації.
блідо-блакитна крапка

ЗМІНІТЬ алгоритм, він може бути приблизним, але лише в певних межах, які ви можете вільно визначити. Ви можете повторювати цикл до тих пір, поки ці межі не стануть настільки малими, наскільки вам потрібно - в принципі (якщо ви дуже обережні, як ви його кодуєте), ви можете досягти тієї самої точності, що і подання числа з плаваючою точкою. Так що так, це залишається приблизним - але лише тому, що плаваюча точка завжди приблизна. Навіть 0,1 можна приблизно представити лише у двійковій системі з плаваючою комою.
Steve314,

@Ravi: Метод Ньютона реалізований за допомогою алгоритму, до якого ви зв’язали - так що просто використовуйте це. Як вихідну точку розгляньте пошук 2 ^ n, що є найближчим до числа, з якого ви хочете взяти корінь, а потім використовуйте 2 ^ (n / 2) як вихідну точку. Однак, оскільки функція f(x)=x^2опукла скрізь, метод Ньютона працює досить добре для неї незалежно від вихідної точки.
Martin B

1
Метод Ньютона насправді є тейлоровою серією O (h ^ 2), ви просто
уточнюєте

Я розрізнив лише два, тому що метод Ньютона повторюється, поки ви не наблизитесь; Ви також можете жорстко закодувати серію Тейлора, яку ви розширили, наскільки вам подобається, і оцінити її під час виконання.
jrockway

9

Обчисліть квадратний корінь з довільною точністю в Python

#!/usr/bin/env python
import decimal

def sqrt(n):
    assert n > 0
    with decimal.localcontext() as ctx:
        ctx.prec += 2 # increase precision to minimize round off error
        x, prior = decimal.Decimal(n), None
        while x != prior: 
            prior = x
            x = (x + n/x) / 2 # quadratic convergence 
    return +x # round in a global context


decimal.getcontext().prec = 80 # desirable precision
r = sqrt(12345)
print r
print r == decimal.Decimal(12345).sqrt()

Вихід:

111.10805551354051124500443874307524148991137745969772997648567316178259031751676
True

6

Це поширене запитання щодо інтерв’ю, яке задає Facebook тощо. Я не думаю, що це хороша ідея використовувати метод Ньютона в інтерв’ю. Що робити, якщо інтерв’юер запитає вас про механізм методу Ньютона, коли ви насправді цього не розумієте?

Я запропонував рішення на основі двійкового пошуку на Java, яке, я вважаю, може зрозуміти кожен.

public int sqrt(int x) {

    if(x < 0) return -1;
    if(x == 0 || x == 1) return x;

    int lowerbound = 1;
    int upperbound = x;
    int root = lowerbound + (upperbound - lowerbound)/2;

    while(root > x/root || root+1 <= x/(root+1)){
        if(root > x/root){
            upperbound = root;
        } else {
            lowerbound = root;
        }
        root = lowerbound + (upperbound - lowerbound)/2;
    }
    return root;
}

Ви можете протестувати мій код тут: leetcode: sqrt (x)


Це не так важко зрозуміти. Ньютон-Рафсон - це звичайна серія Тейлора ...
Патрік

6

Знайшов чудову статтю про цілі квадратні корені .

Це дещо вдосконалена версія, яка вона там представлена:

unsigned long sqrt(unsigned long a){
    int i;
    unsigned long rem = 0;
    unsigned long root = 0;
    for (i = 0; i < 16; i++){
        root <<= 1;
        rem = (rem << 2) | (a >> 30);
        a <<= 2;
        if(root < rem){
            root++;
            rem -= root;
            root++;
        }
    }
    return root >> 1;
}

Ось ще одна стаття, що пояснює цей алгоритм (який досить легко виконати вручну за допомогою паперу та олівця): mathforum.org/library/drmath/view/52610.html
nibot

4

Ось спосіб отримання квадратного кореня за допомогою тригонометрії. Це не найшвидший алгоритм на довгій стрільбі, але він точний. Код у javascript:

var n = 5; //number to get the square root of
var icr = ((n+1)/2); //intersecting circle radius
var sqrt = Math.cos(Math.asin((icr-1)/icr))*icr; //square root of n
alert(sqrt);

4

Існує алгоритм, який я вивчав у школі, за допомогою якого можна обчислити точні квадратні корені (або довільно великої точності, якщо корінь є ірраціональним числом). Це, безумовно, повільніше, ніж алгоритми Ньютона, але це точно. Скажімо, ви хочете обчислити квадратний корінь з 531.3025

По-перше, ви ділите своє число, починаючи з десяткової коми, на групи з 2 цифр:
{5} {31}. {30} {25}
Потім:
1) Знайдіть найближчий квадратний корінь для першої групи, менший або рівний фактичний квадратний корінь першої групи: sqrt ({5})> = 2. Цей квадратний корінь - це перша цифра вашої остаточної відповіді. Позначимо цифри, які ми вже знайшли з нашого кінцевого квадратного кореня, як B. Отже, на даний момент часу B = 2.
2) Далі обчислюємо різницю між {5} та B ^ 2: 5 - 4 = 1.
3) Для всіх наступних Двозначні групи роблять наступне: Знайти X - наступна цифра вашого кореня, така що 131> = ((B * 20) + X) * X. X = 3. 43 * 3 = 129 <131. Тепер B = 23. Крім того, оскільки у вас немає більше 2-значних груп ліворуч від десяткової коми, ви знайшли всі цілі цифри вашого кінцевого кореня.
Помножте залишок на 100, а потім додайте його до другої групи: 100 + 31 = 131.

4) Повторіть те саме для {30} та {25}. Отже, ви маєте:
{30}: 131 - 129 = 2. 2 * 100 + 30 = 230> = (23 * 2 * 10 + X) * X -> X = 0 -> B = 23.0
{25}: 230 - 0 = 230. 230 * 100 + 25 = 23025. 23025> = (230 * 2 * 10 + X) * X -> X = 5 -> B = 23.05 Алгоритм виглядає таким чином складним, але він набагато простіший це на папері, використовуючи ті самі позначення, що і для "довгого ділення", яке ви вивчали в школі, за винятком того, що ви не робите ділення, а натомість обчислюєте квадратний корінь.
Кінцевий результат = 23.05.


3
// Fastest way I found, an (extreme) C# unrolled version of:
// http://www.hackersdelight.org/hdcodetxt/isqrt.c.txt         (isqrt4)

// It's quite a lot of code, basically a binary search (the "if" statements)
// followed by an unrolled loop (the labels).
// Most important: it's fast, twice as fast as "Math.Sqrt".
// On my pc: Math.Sqrt ~35 ns, sqrt <16 ns (mean <14 ns)

private static uint sqrt(uint x)
{
    uint y, z;
    if (x < 1u << 16)
    {
        if (x < 1u << 08)
        {
            if (x < 1u << 04) return x < 1u << 02 ? x + 3u >> 2 : x + 15u >> 3;
            else
            {
                if (x < 1u << 06)
                { y = 1u << 03; x -= 1u << 04; if (x >= 5u << 02) { x -= 5u << 02; y |= 1u << 02; } goto L0; }
                else
                { y = 1u << 05; x -= 1u << 06; if (x >= 5u << 04) { x -= 5u << 04; y |= 1u << 04; } goto L1; }
            }
        }
        else                                             // slower (on my pc): .... y = 3u << 04; } goto L1; }
        {
            if (x < 1u << 12)
            {
                if (x < 1u << 10)
                { y = 1u << 07; x -= 1u << 08; if (x >= 5u << 06) { x -= 5u << 06; y |= 1u << 06; } goto L2; }
                else
                { y = 1u << 09; x -= 1u << 10; if (x >= 5u << 08) { x -= 5u << 08; y |= 1u << 08; } goto L3; }
            }
            else
            {
                if (x < 1u << 14)
                { y = 1u << 11; x -= 1u << 12; if (x >= 5u << 10) { x -= 5u << 10; y |= 1u << 10; } goto L4; }
                else
                { y = 1u << 13; x -= 1u << 14; if (x >= 5u << 12) { x -= 5u << 12; y |= 1u << 12; } goto L5; }
            }
        }
    }
    else
    {
        if (x < 1u << 24)
        {
            if (x < 1u << 20)
            {
                if (x < 1u << 18)
                { y = 1u << 15; x -= 1u << 16; if (x >= 5u << 14) { x -= 5u << 14; y |= 1u << 14; } goto L6; }
                else
                { y = 1u << 17; x -= 1u << 18; if (x >= 5u << 16) { x -= 5u << 16; y |= 1u << 16; } goto L7; }
            }
            else
            {
                if (x < 1u << 22)
                { y = 1u << 19; x -= 1u << 20; if (x >= 5u << 18) { x -= 5u << 18; y |= 1u << 18; } goto L8; }
                else
                { y = 1u << 21; x -= 1u << 22; if (x >= 5u << 20) { x -= 5u << 20; y |= 1u << 20; } goto L9; }
            }
        }
        else
        {
            if (x < 1u << 28)
            {
                if (x < 1u << 26)
                { y = 1u << 23; x -= 1u << 24; if (x >= 5u << 22) { x -= 5u << 22; y |= 1u << 22; } goto La; }
                else
                { y = 1u << 25; x -= 1u << 26; if (x >= 5u << 24) { x -= 5u << 24; y |= 1u << 24; } goto Lb; }
            }
            else
            {
                if (x < 1u << 30)
                { y = 1u << 27; x -= 1u << 28; if (x >= 5u << 26) { x -= 5u << 26; y |= 1u << 26; } goto Lc; }
                else
                { y = 1u << 29; x -= 1u << 30; if (x >= 5u << 28) { x -= 5u << 28; y |= 1u << 28; } }
            }
        }
    }
    z = y | 1u << 26; y /= 2; if (x >= z) { x -= z; y |= 1u << 26; }
Lc: z = y | 1u << 24; y /= 2; if (x >= z) { x -= z; y |= 1u << 24; }
Lb: z = y | 1u << 22; y /= 2; if (x >= z) { x -= z; y |= 1u << 22; }
La: z = y | 1u << 20; y /= 2; if (x >= z) { x -= z; y |= 1u << 20; }
L9: z = y | 1u << 18; y /= 2; if (x >= z) { x -= z; y |= 1u << 18; }
L8: z = y | 1u << 16; y /= 2; if (x >= z) { x -= z; y |= 1u << 16; }
L7: z = y | 1u << 14; y /= 2; if (x >= z) { x -= z; y |= 1u << 14; }
L6: z = y | 1u << 12; y /= 2; if (x >= z) { x -= z; y |= 1u << 12; }
L5: z = y | 1u << 10; y /= 2; if (x >= z) { x -= z; y |= 1u << 10; }
L4: z = y | 1u << 08; y /= 2; if (x >= z) { x -= z; y |= 1u << 08; }
L3: z = y | 1u << 06; y /= 2; if (x >= z) { x -= z; y |= 1u << 06; }
L2: z = y | 1u << 04; y /= 2; if (x >= z) { x -= z; y |= 1u << 04; }
L1: z = y | 1u << 02; y /= 2; if (x >= z) { x -= z; y |= 1u << 02; }
L0: return x > y ? y / 2 | 1u : y / 2;
}

3

Перше, що мені спадає на думку: це гарне місце для використання двійкового пошуку (натхненне цими чудовими підручниками )

Для того, щоб знайти квадратний корінь vaule, ми досліджуємо numberв (1..value)якому пророк правда в перший раз. Предіктором, який ми обираємо, є number * number - value > 0.00001.

double square_root_of(double value)
{
     assert(value >= 1);
     double lo = 1.0;
     double hi = value;

     while( hi - lo > 0.00001)
     {
          double mid = lo + (hi - lo) / 2 ;
          std::cout << lo << "," << hi << "," << mid << std::endl;
          if( mid * mid - value > 0.00001)    //this is the predictors we are using 
          {
              hi = mid;
          } else {
              lo = mid;
          }

     }

    return lo;
 }

2

використовувати двійковий пошук

public class FindSqrt {

    public static void main(String[] strings) {

        int num = 10000;
        System.out.println(sqrt(num, 0, num));
    }

    private static int sqrt(int num, int min, int max) {
        int middle = (min + max) / 2;
        int x = middle * middle;
        if (x == num) {
            return middle;
        } else if (x < num) {
            return sqrt(num, middle, max);
        } else {
            return sqrt(num, min, middle);
        }
    }
}

використовуйте floats замість int, щоб отримати точний результат
Nikita P

1

Загалом, квадратний корінь з цілого числа (наприклад, 2) може бути лише апроксимований (не через проблеми з арифметикою з плаваючою комою, а тому, що це ірраціональні числа, які неможливо точно обчислити).

Звичайно, деякі наближення кращі за інші. Я маю на увазі, звичайно, що значення 1,732 є кращим наближенням до квадратного кореня з 3, ніж 1,7

Метод, використовуваний кодом за цим посиланням, працює, приймаючи перше наближення та використовуючи його для обчислення кращого наближення.

Це називається методом Ньютона, і ви можете повторювати обчислення з кожним новим наближенням, поки воно не буде достатньо точним для вас.

Насправді повинен бути якийсь спосіб вирішити, коли зупинити повторення, інакше воно триватиме вічно.

Зазвичай ви зупиняєтесь, коли різниця між наближеннями менша за значення, яке ви вирішили.

EDIT: Я не думаю, що може бути простіша реалізація, ніж дві, які ви вже знайшли.


Обережно! Ви хочете померти як Гіппас? en.wikipedia.org/wiki/Hippasus ?
Стефано Боріні

Якби ірраціональні числа були смертельними, ми б усі були мертві, якщо говорили про кола.
pavium

Звучить як давньогрецький еквівалент DCMA.
Стівен С


0

Просте рішення, яке може мати справу з плаваючим квадратним коренем та довільною точністю за допомогою двійкового пошуку

закодований в рубін

include Math

def sqroot_precision num, precision
  upper   = num
  lower   = 0
  middle  = (upper + lower)/2.0

  while true do
    diff = middle**2 - num

    return middle if diff.abs <= precision

    if diff > 0
      upper = middle
    else diff < 0
      lower = middle
    end

    middle = (upper + lower)/2.0
  end 
end

puts sqroot_precision 232.3, 0.0000000001

0

Скажімо, ми намагаємось знайти квадратний корінь з 2, а ви маєте оцінку 1,5. Ми скажемо a = 2 і x = 1,5. Для обчислення кращої оцінки ми поділимо a на x. Це дає нове значення y = 1,333333. Однак ми не можемо просто взяти це як наступну оцінку (чому б і ні?). Нам потрібно усереднити його за попередньою оцінкою. Отже, наша наступна оцінка, xx буде (x + y) / 2, або 1,416666.

Double squareRoot(Double a, Double epsilon) {
    Double x = 0d;
    Double y = a;
    Double xx = 0d;

    // Make sure both x and y != 0.
    while ((x != 0d || y != 0d) && y - x > epsilon) {
        xx = (x + y) / 2;

        if (xx * xx >= a) {
            y = xx;
        } else {
            x = xx;
        }
    }

    return xx;
}

Епсилон визначає, наскільки точною має бути апроксимація. Функція повинна повернути перше наближення x, яке вона отримує, що задовольняє abs (x * x - a) <epsilon, де abs (x) - абсолютне значення x.

square_root(2, 1e-6)
Output: 1.4142141342163086

0

Ну, вже є досить багато відповідей, але тут йде моя. Це найпростіший шматок коду (для мене), ось алгоритм для нього.

І код в python 2.7:

from __future__ import division 
val = 81
x = 10
def sqr(data,x):
    temp = x - ( (x**2 - data)/(2*x))
    if temp == x:
        print temp
        return
    else:
        x = temp
        return sqr(data,x)
    #x =temp 
    #sqr(data,x)
sqr(val,x)

-5

Обчислити квадратний корінь із числа за допомогою вбудованої функції

# include"iostream.h"
# include"conio.h"
# include"math.h"
void main()
{
clrscr();
float x;
cout<<"Enter the Number";
cin>>x;

 float squreroot(float);  
 float z=squareroot(x);
 cout<<z;


float squareroot(int x)
    {


 float s;
 s = pow(x,.5)  
 return(s);
 }    
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.