Top.Mail.Ru
Ответы

Корень 3-ей степери на си шарп без sqrt и math.pow.

В задаче по программированию есть часть задания , где нужно найти корень 3-ей степени из числа , а я хз как его найти. Предпологаю что есть схемка похожая по типу нахождения квадратного корня.

Это для квадратного корня

using System;
public class Test
{
public static void Main()
{
int pref = 49;
int kd = 0;
int k=1;
while (pref>0)
{
pref-=k;
kd++;
k+=2;
}
Console.WriteLine(kd);
}
}

По дате
По рейтингу
Аватар пользователя
Новичок
5мес

Целочисленный корень или вещественный?
Если вещественный, то корень ищется так: https://ru.wikipedia.org/wiki/Алгоритм_нахождения_корня_n-ной_степени
Если целочисленный, то проще использовать бинарный поиск. Что-то вроде такого (на C, но C# не сильно отличается):

1234567891011121314
 int icbrt(int n) {
  int l = 0, r = n;
  while (l < r) {
    int m = (l + r) / 2;
    if (m * m * m < n) {
      l = m + 1;
    } else if (m * m * m > n) {
      r = m - 1;
    } else {
      return m;
    }
  }
  return l;
} 
Аватар пользователя
Искусственный Интеллект
5мес

Если только с этими ограничениями, то так:

1
 public static double Root3(double x) => Math.Exp(1d / 3d * Math.Log(Math.Abs(x))) * Math.Sign(x); 


Как видишь, ни sqrt, ни pow тут нет.

Если вообще нельзя использовать Math, то экспоненту и логарифм можно сделать самому через Тейлора, а как сделать Abs и Sign, надеюсь, ты и сам догадаешься...

Аватар пользователя
Высший разум
5мес

Алгоритм довольно примитивный (основанный на представлении квадрата числа в виде суммы последовательных нечётных чисел), сходится медленно, за O(√x). Можно, конечно, поискать, как раскладывается куб, но зачем? Проще применить бинарный поиск, он сходится за логарифм. Или разложи кубический корень в ряд Тейлора, но у него быстрая сходимость только финально, поэтому сначала надо будет найти достаточно точное приближение.

Вот пример для бинарного поиска на положительных числах (если нужны отрицательные, пошамань с подбором границ и с проверкой условия, поставь отладочную печать, чтобы понять, как работает).

123456789101112131415
 using System;
class Test {
  static void Main() {
    const double eps = 1e-9;
    double cube = double.Parse(Console.ReadLine());
    double l = cube >= 1 ? 1 : 0,
           r = cube >= 3 ? cube / 2.0 : cube;
    while (r - l > eps) {
      double m = (l + r) / 2.0;
      if (m * m * m > cube) r = m;
      else l = m;
    }
    Console.WriteLine((l + r) / 2.0);
  }
} 

Константа eps регулирует точность.

Если надо в целых числах, то подмени типы, а точность должна быть 1, ближе не подберёшь.

Аватар пользователя
Мыслитель
5мес

Вариант 1 (итеративно):


123456789101112131415161718192021222324252627282930313233343536373839404142
 using System;  
  
public class CubeRoot  
{  
    private const double Tolerance = 0.0001;  
    public static double CalculateCubeRootIterative(double number)  
    { 
        if (double.IsNaN(number) || double.IsInfinity(number))  
            return double.NaN;  
  
        double low, high;  
        if (number >= 0)  
        {  
            low = 0;  
            high = number;  
        }  
        else  
        {  
            low = number;  
            high = 0;  
        }  
   
        while (high - low > Tolerance)  
        {  
            double mid = low + (high - low) / 2; 
            double cube = mid * mid * mid; 
  
            if (Math.Abs(cube - number) < Tolerance)  
            {  
                return mid;  
            }  
            else if (cube > number)  
            {  
                high = mid;  
            }  
            {  
                low = mid;  
            }  
        }  
  
        return low; 
    } 

Вариант 2 (рекурсивно):


1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
 public static double CalculateCubeRootRecursive(double number, double low, double high) 
    { 
       // Если число не число (NaN) или бесконечность, то и корень будет не числом 
        if (double.IsNaN(number) || double.IsInfinity(number)) 
           return double.NaN; 
 
        if (high - low <= Tolerance) 
        { 
           return low; 
        } 
 
        double mid = low + (high - low) / 2; 
        double cube = mid * mid * mid; 
 
        if (Math.Abs(cube - number) < Tolerance) 
        { 
            return mid; 
        } 
        else if (cube > number) 
        { 
            return CalculateCubeRootRecursive(number, low, mid); 
        } 
        else 
        { 
           return CalculateCubeRootRecursive(number, mid, high); 
        } 
    } 
 
     public static double CalculateCubeRootRecursive(double number) 
     { 
        if (number >= 0) 
        { 
           return CalculateCubeRootRecursive(number, 0, number); 
        } 
        else 
        { 
           return CalculateCubeRootRecursive(number, number, 0); 
        } 
     } 
 
    public static void Main(string[] args) 
    { 
      // Проверим, как это все работает: 
        double[] numbers = { 27, -8, 125, 0.125, 0, 10, -2, 1000, -1000, 1.7, double.NaN, double.PositiveInfinity, double.NegativeInfinity }; 
        Console.WriteLine("Кубический корень:\n"); 
 
        foreach (double number in numbers) { 
           double rootIterative = CalculateCubeRootIterative(number); 
           double rootRecursive = CalculateCubeRootRecursive(number); 
            Console.WriteLine($"Число: {number}, Итеративный корень: {rootIterative}, Рекурсивный корень: {rootRecursive}"); 
        } 
         Console.WriteLine("\n"); 
        Console.WriteLine("Производительность:\n"); 
 
        int iterations = 1000000; 
        double numberTest = 64.0; 
 
        var swIterative = System.Diagnostics.Stopwatch.StartNew(); 
          for (int i = 0; i < iterations; i++) 
             CalculateCubeRootIterative(numberTest); 
 
         swIterative.Stop(); 
         var swRecursive = System.Diagnostics.Stopwatch.StartNew(); 
          for (int i = 0; i < iterations; i++) 
             CalculateCubeRootRecursive(numberTest);

    } 
}