Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
687 / 444 / 209
Регистрация: 18.10.2020
Сообщений: 1,606
1

Возведение вещественного числа в вещественную степень

16.09.2022, 23:41. Показов 1258. Ответов 8

Author24 — интернет-сервис помощи студентам
Решил написать функцию pow, может кому понадобится
funcs.h
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#pragma once
#include <stdio.h>
#include <time.h>
 
const double EPS = 1.e-15;
 
double Simpson(double f_sh(double), double a, double b, int n = 64);//формула Симпсона (интегрирование)
 
double FAbs(double x);//модуль числа
 
double power(double a, double b);//Возведение вещественного числа в вещественную степень (кроме отрицательных, их только в целые)
double ln(double x);//логарифм
double powerd(double a, long b);//возведение в целые степени

funcs.cpp
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include "funcs.h"
 
double FAbs(double x)//модуль
{
    if(x > 0)
        return x;
    return -x;
}
 
double Simpson(double f_sh(double), double a, double b, int n)//h*(f0+f2n+2*(f2k)+4*(f2k-1))/3
{//интеграл от функции
    double integ = 0, h = (b - a) / (2 * n), x0 = a;
    integ = f_sh(b) + f_sh(a);
    for (int i = 1; i < 2 * n; i++)
    {
        x0 += h;
        integ += 2 * f_sh(x0) * ((i + 1) % 2) + 4 * f_sh(x0) * (i % 2);
    }
    return integ * h / 3;
}
 
double powerd(double a, long b)
{   
    double S = 1.0;
    while(b != 0)
    {
        if((b & 1) != 0)
            S *= a;
        a *= a;
        b >>= 1;
    }
    return S;
}
 
double ln(double x)
{
    x = (x - 1)/(1 + x);
    double el = x, S = 0;
    x *= x;
    for(int i = 1; FAbs(el) > EPS; i += 2)
    {
        S += el / i;
        el *= x;
    }
    return S * 2;
}
 
double power(double a, double b)
{
    
    if(a == 0 || a == 1 || a == -1)
        return (int)b % 2 ? a : a * a;
    
    double tmp = FAbs(b), sum2 = 0, sum1 = powerd(a, (long)tmp);
    tmp -= (long) tmp;
    
    if(tmp > EPS)
    {
        double LN = (FAbs(a) > 1 ? ln(a) : -ln(1.0 / a)) * tmp;
        double el = 1.0;
        for(int i = 1; FAbs(el) > EPS; i++)
        {
            sum2 += el;
            el *= LN / i;
        }
    }   
    else
        sum2 = 1;
    
    sum2 *= sum1;
    if(b > 0)
        return sum2;
    return 1.0 / sum2;
}


main.cpp
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include "funcs.h"
#include <math.h>
 
int main()
{   
    for(double a = -2.4; a < 2.6; a += 1)
    {
        for(double b = -1.0; b < 3.1; b += 3)
            printf("%g^%g = %3.17lf ", a, b, power(a, b));
        puts("\n");
    }
    
    for(double a = -2.4; a < 2.6; a += 1)
    {
        for(double b = -1.0; b < 3.1; b += 3)
            printf("%g^%g = %3.17lf ", a, b, pow(a, b));
        puts("\n");
    }
    
    time_t st, fin;
    
    st = clock();
    for(int i = 0; i < 100000; i++)
        power(2, 10);
    fin = clock();
    printf("\n%d\n", fin - st);
    
    for(int i = 0; i < 100000; i++)
        pow(2, 10);
    fin = clock();
    printf("\n%d\n", fin - st);
    
    st = clock();
    for(int i = 0; i < 100000; i++)
        power(2, 10.2);
    fin = clock();
    printf("\n%d\n", fin - st);
    
    for(int i = 0; i < 100000; i++)
        pow(2, 10.2);
    fin = clock();
    printf("\n%d\n", fin - st);
    
            
    getchar();
    return 0;
}


Добавлено через 11 минут
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
double powerd(double a, long b)
{   
    double S = 1.0;
    while(b)
        if(b % 2)
        {
            S *= a;
            b--;
        }
        else
        {
            a *= a;
            b /= 2;
        }
    return S;
}
аналог powerd, но без всяких >> и &
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
16.09.2022, 23:41
Ответы с готовыми решениями:

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

Рекурсивные функции: возведение вещественного числа в целую степень
Цель: Надо разработать программу для возведения вещественного числа в целую степень. Как...

Возведение в вещественную степень
Здравствуйте, требуется ваша помощь. У меня дано float a,x,n, вычислить a^x с точностью...

Программа возведения комплексного числа в вещественную степень !!!
Программа возведения комплексного числа в вещественную степень : (a+Bi) в степени c (по формуле...

Возведение числа а в степень n
Возведение числа а в степень n ,задача не проста чем , 1&lt;=а&lt;=10 | 1&lt;=n&lt;=7000 Степень может быть...

8
2277 / 1768 / 741
Регистрация: 27.07.2012
Сообщений: 5,251
16.09.2022, 23:50 2
Цитата Сообщение от programmer_08 Посмотреть сообщение
Решил написать функцию pow
А зачем? Просто из спортивного интереса?
0
687 / 444 / 209
Регистрация: 18.10.2020
Сообщений: 1,606
16.09.2022, 23:59  [ТС] 3
Цитата Сообщение от John Prick Посмотреть сообщение
А зачем? Просто из спортивного интереса?
ага, а вообще подтолкнула одна тема, где человечек собирался написать свою мат библу.
0
Нарушающий
417 / 305 / 46
Регистрация: 13.04.2022
Сообщений: 1,759
17.09.2022, 01:31 4
Было бы интересно дать оценку точности тех функций, где присутствует циклическое накопление ошибок округления.

Не зная точности, это "кустарное, неизвестного качества".
А вот если бы функция powerd давала верхнюю/нижнюю оценку, она стала бы более полезной чем встроенная, которая "стараюсь как можно точнее, погрешность сам вычисляй на доверии что мантисса верна"

Добавлено через 45 минут
Я сравнил с фабричным pow(), для 0.8^20 получил нормализованную ошибку 1е-15 - это самая большая из наспех найденных.

Большинство ошибок были вверх, но для 0.7^N ошибки были вниз.

В абсолютных значениях, первое число это pow(), второе - разница с powerd():

0.7^20 = 0.000797922662976118944773429309 / -0.000000000000000000108420217249
0.8^20 = 0.011529215046068483005448079837 / 0.000000000000000012143064331838

Что такое нормализованная ошибка 1е-15?
64-битное представление double содержит 53 бит мантиссы, или 16 десятичных цифр, 1е-15 изменит последнюю цифру.

Поменяв внутренние вычисления в powerd() на long double, я получил точное совпадение с встроенной, за исключением:
0.3^31 - 2e-16
0.6^31 - 2e-16
0.9^51 - 2e-16

Кликните здесь для просмотра всего текста
C
1
2
3
4
5
6
7
8
9
10
11
12
13
double powerd(double x, long b)
{   
    long double S = 1.0;
    long double a = x;
    while(b != 0)
    {
        if((b & 1) != 0)
            S *= a;
        a *= a;
        b >>= 1;
    }
    return (double)S;
}


Добавлено через 11 минут
С логарифмом проблема - вызов ln(1000 000 000) от миллиарда занимает 20 секунд, и ошибается на 0.0007.

Для плавающей точки скорость вычисления логарифма не должна зависеть от величины числа, т.к. мантисса уже нормализована, нужно потом только приплюсовать к результату степень умноженную на ln(2).
1
Модератор
Эксперт функциональных языков программированияЭксперт Python
36601 / 20330 / 4220
Регистрация: 12.02.2012
Сообщений: 33,644
Записей в блоге: 13
17.09.2022, 10:34 5
Чем она лучше стандартной?

Цитата Сообщение от programmer_08 Посмотреть сообщение
аналог powerd, но без всяких >> и &
- а чем битовые операции плохи?
Они быстро выполняются...
0
Комп_Оратор)
Эксперт по математике/физике
8950 / 4704 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
17.09.2022, 10:51 6
Цитата Сообщение от programmer_08 Посмотреть сообщение
double tmp = FAbs(b), sum2 = 0, sum1 = powerd(a, (long)tmp);
programmer_08, формат чисел с плавающей точкой (нпример IEEE 754-2008) позволяет хранить числа намного превышающее максимальный предел long.
0
687 / 444 / 209
Регистрация: 18.10.2020
Сообщений: 1,606
17.09.2022, 15:13  [ТС] 7
IGPIGP, знаем, но с трудом представляю, что кому-то нужно будет возводить в степень, буольшую 2*10^6 хотя бы) плюс в таком случае всегда можно обойтись циклами.
Цитата Сообщение от Catstail Посмотреть сообщение
- а чем битовые операции плохи?
я их не понимаю, поэтому для себя написал ещё и функцию без их использования. Дойдут руки изучу и их (функцию с ними нашёл на просторах интернета)
Цитата Сообщение от QueryMonkey Посмотреть сообщение
Для плавающей точки скорость вычисления логарифма не должна зависеть от величины числа, т.к. мантисса уже нормализована, нужно потом только приплюсовать к результату степень умноженную на ln(2).
этого вот не понял, ну по формуле как раз подсчёт ещё как зависит от числа, но вот как избавиться от этой зависимости - не знаю.
0
Комп_Оратор)
Эксперт по математике/физике
8950 / 4704 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
17.09.2022, 15:44 8
Цитата Сообщение от programmer_08 Посмотреть сообщение
IGPIGP, знаем, но с трудом представляю, что кому-то нужно будет возводить в степень, буольшую 2*10^6
Вопросов больше нет. Для системы без сопроцессора и кобыла - невеста. (Дворник - Остапу Сулейману де Берта Мария Бендеру-бею. Не есквайеру. 12 стульев).
0
Нарушающий
417 / 305 / 46
Регистрация: 13.04.2022
Сообщений: 1,759
17.09.2022, 16:58 9
programmer_08,

Мантисса в double нормализована, всегда 1 <= m < 2. Ее легко извлечь одной операцией
Для такого числа ваш код даст предсказуемую высокую скорость и точность.

Затем к результату добавить поправку от двоичной экспоненты, которую убирали.

Ln(m*2x) = ln(m) + x*ln(2)
1
17.09.2022, 16:58
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
17.09.2022, 16:58
Помогаю со студенческими работами здесь

Возведение числа в степень n
Здравствуйте. Помогите пожалуйста разобраться с задачей. Возвести, целое число, в степень n....

Возведение числа в степень!
Хай всем кто на форуме! Помогите с задачей! Надо возвести число в степень #include &lt;iostream&gt; ...

Возведение числа в степень n-1
Есть формула {(-1)}^{n-1}*{3}^{n-1} , n увеличивается циклом на 1. Как записать числа в степень n-1...

Возведение числа n в степень m.
Написать программу - возведение числа n в m-ю степень. Входные данные поступают с клавиатуры....

Возведение числа в степень
Помогите написать программу, возводящщую число M в степень N (-10&lt;M&lt;10, 0&lt;N&lt;10 - проверить...

Возведение из числа степень
Прошу помочь. Вводим любое число n и надо возвести её степень. (притом, должно быть или 2 в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru