Степень от отрицательного числа
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.215] |
|
|
Правила раздела Visual Basic: Общие вопросы
FAQ Сайта
FAQ Раздела
Кладовка
Наши Исходники
API-Guide
Поиск по Разделу
MSDN Library Online
Google
Степень от отрицательного числа
|
Сообщ.
#1
,
|
|
|
|
Писал анализатор выражений и столкнулся с неприятной вещью!
В VB полностью отсутствует такое понятие, как возведение в степень отрицательного основания; если степень натуральна все решается очень быстро, но например, (-8)^(1/3) ставит меня и комп в тупик!Кроме того, степень может быть еще и туподесятичной (0.3432567) и тут вообще трудно понять :возводится или нет! Кто знает способы , пожалуйста, напишите! К примеру, калк в винде все это считает с закрытыми глазами! |
|
Сообщ.
#2
,
|
|
|
|
Lucifer, интересные у тебя основы...
Ну на самом деле возводить отрицательные числа в нецелую степень можно и нужно. К примеру, (-1)^(1/3) = 3 корня из -1 = -1. Хотя арифметический корень четной степени из большинства чисел извлечь и нельзя, но данная операция в математике производится. Для этого вводится поле комплексных чисел С. Например, (-1)^(1/2) = i - мнимая единица. Но это врядли понадобится для обычного анализатора. На самом деле решение выражения x^y, где x<0, очень простое: Надо проверить что у четный, т.е. не делится на 2 без остатка. Если он делится, то значит результат возведения в степепень будет комплексный. Если у нечетный то выражение x^y можно записать так: -(abs(x)^y). |
|
Сообщ.
#3
,
|
|
|
|
"(-1)^(1/3)=((-1)^(0.5))^(2/3)"
Зачем делать такие выкладки с потерей области значений, они только усложнят задачу. 2Lamerroot Ты предлагаешь проверить на четность дробь? Скорее всего, ты имел в виду инверсию дроби 1/3=>3/1 ; 1/8=>8/1 Но в таком случае мы решаем только часть задачи! К примеру, таким способом невозможно узнать ничего о (-1)^(19/52); (-1)^(3/7); В одном выражении(без дополнительных раскладок ) решения нет - в другом есть! После подсчета каждой степени получаем десятичную дробь с ужасающим периодом. И теперь ни о какой четности не может быть и речи! |
|
Сообщ.
#4
,
|
|
|
|
2 Golovastik:
Ты чё прикалываешься ? Я имел ввиду именно дробь, десятичную дробь! Хотя понятие четности для дроби в принципе нет, но я просто не знал как это ещё детеменировать.Естественно вычисление дробей в степени будет давать некоторые погрешности в вычислениях, связанные с приближенным представлением числа в ПК. Вообще говоря, нельзя будет достигнуть большей точности, чем тот порядок разряда, который позволяет точно показать знаковый тип. Что касается четноти дроби, я попытаюсь показать, что имел ввиду. Рассмотрим дробь 3/24=0.125. Конечно об остатке от деления десятичной дроби говорить прямо нельзя, это абстакция. Однако про деления без остатка дробной части 125 сказать можно. Фактически дробь четная, если при делении её дробная часть является четной. 125/2=62.5, следовательно можно сказать, что дробь нечетная. НЕМНОГО ВНИМАНИЯ, я в прошлом посте кое-что перепутал, ответ выражения будет существовать только если дробь (т.е. её дробная часть) четная, а не наоборот, т.к. нам важна только нечетность делимого. Всё что я только-что сказал касается лишь рациональных дробей, про множесво вещественных чисел я и не говорил. Golovastik, ты только что привел две иррациональные дроби. Естественно их нельзя ни на что делить, т.к. они и так представленны приближенно и последний разряд округляется. Про них я в посте ничего неговорил. С ними дело обстоит куда сложнее. В теории чисел есть ондна теоремка, она говорит, что, если у дроби делимое и делитель - простые числа, то дробь будет строго периодической (период будет начинаться с первого дробного разряда). Например, 3/7=0.428571428571429 - double (0.428571428571428571428571428571429 - калькулятор). 7 и 3 - простые числа, поэтому дробь имеет период 428571. Рассмотрим дробь 19/52 = 0.365384615384615 - double (0.365384615384615384615384615384615 - калькулятор). Как видно периодичность начинается только после 0.36538. Скажем, в 1/3 = 0,33333333333333333333 период совсем простой. Так вот если дробь строго переодичекая, то в неё можно возвести отрицательное число по правилу -(abs(x)^y). Естественно результат будет довольно неточный. Хочу так же заметить, что все мои выкладки касаются десятичного представления дроби, а никак не аналитического. Добавлено в : И ещё хочу немного сказать о продблемах данного подхода. Возмем число 1/23=0.043478260869565217391304347826087. Делимое и делитель простые, дробь строго периодическая, но период - 0434782608695652173913. Даже виндовый калькулятор не смог показать 2 периодических блока цифр. А ведь число цифр в периоде может быть и больше, т.е. в double весь период не влезет. |
|
Сообщ.
#5
,
|
|
|
|
2Lamerroot
Я внимательно прочитал твой пост, и кое-что меня порадовало, а что-то осталось непонятным. Пункт 1 Действие с остатком приводит к хорошим результатам и для написания не представляет особых трудностей (спасибо, я обязательно этим воспользуюсь) Пункт 2 НО! Для решения основной задачи недостаточно рассмотреть частные случаи. ВСЕ рациональные числа нуждаются в обработке. Я бы хотел напомнить Lamerroot'у , что у нас тема VB, т.е. не теория математики, а практическое применение в её среде. Да, если период начинается с первого дробного разряда, то можно воспользоваться –(abs(x)^y),но для этого понадобится застрингить переменную и проверять циклами по каждому знаку (а если период окажется чрезмерно большой)! ; но , в принципе , если нет других решений , все равно придется заниматься всем этим геморроем! Пункт 3 Так ничего и не ясно , что делать с подавляющим числом остальных рациональных чисел ( к примеру, те же 17/69 и 19/52 ) Даже найдя период ( он у таких чисел всегда имеется) мы ничего не сможем доказать предыдущими методами! Можно также перевести дробь в обыкновенную, но любой разумный программер скажет, что это самоубийство! Пункт 4 ( к п. 2,3) Остается последний вопрос! Позволяет ли VB поддерживать более точные типы данных, или он все же больше visual , чем инструмент для точной обработки? |
|
Сообщ.
#6
,
|
|
|
|
Lamerroot vse pravilno napisal. Esli drob obiknovennaja, to vse prosto: dla otritsatelnix osnovanij nuzno proverit lish delimoje stepeni na chetnost:
![]() ![]() if delimoje stepeni.Chetnoje = True Then Znachenije = Abs(x) ^ y if delimoje stepeni.Chetnoje = False Then if delitel stepeni.Chetnoje = False Then Znachenije = -Abs(x) ^ y if delitel stepeni.Chetnoje = True Then "Net Reshenija" ' kompleksnoje znachenije End if A vot s desatichnimi uze posloznee... Lamerroot: В теории чисел есть ондна теоремка, она говорит, что, если у дроби делимое и делитель - простые числа, то дробь будет строго периодической ....Так вот если дробь строго переодичекая, то в неё можно возвести отрицательное число по правилу -(abs(x)^y). Odnako, esli dva chisla - prostije, to eto sovsem ne znachit, chto drob budet pereodicheskoj, naprimer: 3/2 = 1.5 1/2 = 0.5 i, sledovatelno, возвести отрицательное число по правилу -(abs(x)^y) ne udastsa. |
|
Сообщ.
#7
,
|
|
|
|
2VBer
А как это ты собираешься выяснить какое делимое и какой делитель?!!! Порядок действия для анализатора "x^(y/z)" : сначала посчитать "y/z" , а потом уже с полученным ответом лезть к "x"!!! |
|
Сообщ.
#8
,
|
|
|
|
Цитата Golovastik,4.08.04, 09:36 ВСЕ рациональные числа нуждаются в обработке. А они и обрабатываются. Цитата Я бы хотел напомнить Lamerroot'у , что у нас тема VB, т.е. не теория математики, а практическое применение в её среде. Да, если период начинается с первого дробного разряда, то можно воспользоваться –(abs(x)^y),но для этого понадобится застрингить переменную и проверять циклами по каждому знаку (а если период окажется чрезмерно большой)! ; но , в принципе , если нет других решений , все равно придется заниматься всем этим геморроем! Так а что я то могу тут сделать? Если хочешь возводить в иррациональную степень, то придется страдать. А вообще, зачем оно тебе, вот разработчики ВБ или даже С++ просто тупо забили на эту проблему. Цитата Так ничего и не ясно, что делать с подавляющим числом остальных рациональных чисел ( к примеру, те же 17/69 и 19/52 ) Даже найдя период ( он у таких чисел всегда имеется) мы ничего не сможем доказать предыдущими методами! Эту глубокую мысль я не совсем понял, но числа нормальные. 17/19 = 0.894736842105263157894736842105263, период здесь 473684210526315789, но он начинается только с третьего дробного знака (0.89|473684210526315789|4736842105263), т.е. дробь не строго периодическая. Значит возводить в эту степень нельзя. Аналогично 19/52 = 0,365|384615|384615|384615|384615 период начинается с четвертой дробной цифры. Цитата Можно также перевести дробь в обыкновенную, но любой разумный программер скажет, что это самоубийство! Да вычисления тут громадные, но что я то могу поделать, математика моё мнение не очень ценит. Цитата Остается последний вопрос! Позволяет ли VB поддерживать более точные типы данных, или он все же больше visual , чем инструмент для точной обработки? Нет. Да и никакой другой язык не поддерживает типы нужной тебе точности. Для вычислений большой точности существуют специальные алгоритмы. Зайди в rambler.ru и набери "Длинная арифметика". Читай и ужасайся. Цитата Odnako, esli dva chisla - prostije, to eto sovsem ne znachit, chto drob budet pereodicheskoj, naprimer: 3/2 = 1.5 1/2 = 0.5 i, sledovatelno, возвести отрицательное число по правилу -(abs(x)^y) ne udastsa. Почему? Для тех кто в танке, я повторяю Цитата ...ответ выражения будет существовать только если дробь (!!!т.е. её дробная часть!!!) четная,..., т.к. нам важна только нечетность делимого. Вот скажи, 5 это четное число? Наверное нет. Следовательно x^1.5 = комплексное число. Аналогично, 22/10 = 2.2, 2 - четное число, значит x^1.5 = -(abs(x)^2.2). Правда, у кого-то может возникнуть вопрос: (-1)^(22/10) = 10 корней из (-1)^22 = 1. На самом деле мы получили неверный ответ. Ответом данного выражения будет модуль: (-1)^(22/10) = |1| = 1 или -1 (лень объяснять почему). Но то, что ответ должен быть отрицательный легко проверить приведя дробь к простому виду: (-1)^(22/10)=(-1)^(11/5) = 11 корней из (-1)^5 = -1. Надеюсь теперь всё всем ясно. |
|
Сообщ.
#9
,
|
|
|
|
Спасибо.
Ясно , даже более того ... |
|
Сообщ.
#10
,
|
|
|
|
Ну вы и математики...
Надо бы вам ТФКП подучить Общая показательная функция есть многозначная функция, включающая в себя отельные ветви функции w = x^z = exp(z*Ln(x)) Главную ветвь получают, когда берут главную ветвь Ln(x). Натуральный логарифм есть функция, обратная функции w = exp(x) в области ее однозначности ln(z) = ln|z|+phi_0*i , phi_0 главное значение аргумента arg(z) Обратное отображение натуральной показательной функции во всей комплексной плоскости обозначают Ln(z) Ln(z) = ln|z|+phi_0*i + 2*Pi*k*i Ну а exp(z) = exp(a+bi) = exp(a)*(cos(b)+isin(b)) Ну так вот, если при возведении в степень отрицательного числа существет чисто вещественное значение, то его и берут, а если нет, то на нет и суда нет. В общем случае все комплексное |
|
Сообщ.
#11
,
|
|
|
|
Не, ну ТФКП ты знаешь, не спорю...
Вижу у тя тут записана общая формула возведения в степень, общая формула логарифма от комплексного числа, тригонометрическая форма записи. Тока что ты предлагаешь с этим делать, я не совсем понял. Ну будет существовать на окружности вещественное значение, и что? Мы же не с комплексными числами работаем, а аргумент любого вещественного числа, если я не ошибаюсь, есть 0, так что ты предлагаешь считать? |
|
Сообщ.
#12
,
|
|
|
|
Цитата Мы же не с комплексными числами работаем, а аргумент любого вещественного числа, если я не ошибаюсь, есть 0, так ты предлагаешь считать? Так вот и нужно при возведении в степень отрицательного числа временно перейти к комплекскным числам. И если одно из значений показательной функции окажется вещественным (тут ты прав аргумент у него 0, ну т.е. < eps), то его и брать в качестве ответа, а если не окажется такого, то error. Квадратное же уравнение в вещественных числах не всегда имеет решение и никто этому не удивляется. |
|
Сообщ.
#13
,
|
|
|
|
to Math:
vi eto, nadejus, v institute proxodite, a to nemnogo ne po sebe stalo ot tvojego otveta? |
|
Сообщ.
#14
,
|
|
|
|
Не понял. Чего-то неясно, или возражения есть? Если непонятно так и скажите. Я примерчик дам, только не счас, а то спать пора
ЗЫ. В Университете проходил. ЗЗЫ. А возражения то должны быть Я ведь не правильно написал, не аргумент ноль, а синус аргумента, то бишь мнимая часть ноль |
|
Сообщ.
#15
,
|
|
|
|
2Math
Сразу видно, интересный у тебя подход к этой задаче (не то, что с дробями возиться B) ) Исходник набросаешь? |
|
Сообщ.
#16
,
|
|
|
|
Признаю свое поражение! Тут я похоже из пушки по воробьям стрельнул. Расписал давеча, что по ТФКП получается. Ну, вот и получается, то о чем выше было сказано 1. Если показатель степени рациональное число, то надо делать как было выше пост #8 от VBer'a. 2. Если показатель степени иррациональцое число, то не существует вещественных значений степени отрицательного числа. Теперь о том как предлагаю считать. Ответ в любом случае будет приближенный и однозначно во всех случаях мы не сможем сказать имеет степень мнимую часть или нет. Итак, формулы останутся прежними, только вместо условий на делимое, будут другие условия 1. Задаем точность eps, представления целого числа. И максимальное число итераций NMAX. Например, ![]() ![]() double eps = 0.0001; int NMAX = 10000; 2. Дальше цикл ![]() ![]() int i = 0; int kRes = 0; double k; while (i<NMAX) { i++; k = (i/y-1.0)/2.0; if (fabs(fabs(k)-(int)(fabs(k)+0.5)) < eps) then { kRes=1; break; } } 3. Дальше проверяем ![]() ![]() if (kRes) { if ( (int)(i/2)*2 == i ) then result = fabs(x) ^ y; else result = -fabs(x) ^ y; } else { // нет решения } ЗЫ. Сорри за C++, VB не владею |
|
Сообщ.
#17
,
|
|
|
|
Та ты и С неочень как-то владеешь. Первый раз вижу в сишном коде оператор 'then'
, а '^' это вообще сумма по модулю 2 (хотя может где-нить в коде он и был у тя переопределен).Цитата 2. Если показатель степени иррациональцое число, то не существует вещественных значений степени отрицательного числа. Ага, ты мне просто открыл глаза, к примеру, 1/3 = 0.(3) - иррациональное число, Я всегда думал, что -1^(1/3) = -1. Но ты прав, вещественных корней нет! Единицы не существует. Особенно было актувльно это говорить, после того, как подробно описал алгоритм возведения отрицаолетьных чисел в иррациональную степень. Не, ну я тебя понимаю, считать в вещественных числах это немодно. Надо переходить на комплексное множество, так код будет круче выглядеть, та и погрузить людей комплексным анализом можно. А как сладка фраза "Если непонятно так и скажите" B)! Я тебе и говорю: "мне не понятно". Я не спорю, что ты может и знаешь, как возводить отрицательные числа в степень. Я не притендую на оптимальность моего алгоритма, но надо же соблюдать корректность по отношению к таким простым смертным, как мы. Да, между прочим, твой код не работает, при любых х и у он сообщает, что решений нет. Исправляй баги. |
|
Сообщ.
#18
,
|
|
|
|
Получите
![]() ![]() // power.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "math.h" int main(int argc, char* argv[]) { double eps = 0.000001; int NMAX = 10000; int i = 0; int kRes = 0; double k; double result; double x = -2.0; double y = 1.0/5.0; while (i<NMAX) { i++; k = (i/y-1.0)/2.0; if (fabs(fabs(k)-(int)(fabs(k)+0.5)) < eps) { kRes=1; break; } } if (kRes) { if ( (int)(i/2)*2 == i ) result = pow(fabs(x), y); else result = -pow(fabs(x), y); } else { // error } if (kRes) { printf("%e",result); } else { printf("error"); } return 0; } И попросил бы без наездов, если сами не смогли разобраться Любое число p/q, где p и q целые называется рациональным числом. Иррационально же, например, число sqrt(2), которое нельзя! представить в виде дроби. Я хоть и не считаю себя спецом в теории чисел, а такие элементарные знания имею в отличие от Вас.А по такой жаре еще и не такие глюки могут быть, я просто редактировал псевдокод VBer'a, ну и кое-что не подчистил ![]() Попробуйте поиграть с параметром у. Возмите 1/3, 2/3,3/5 и увидете, что все работает. Поиграйте eps. Ну и если Вы такой крутой, то ответте мне на вопрос, как оценить мнимую часть полученной степени (это может пригодиться если eps грубое,например 0.01) ? Вся необходимая информация у Вас есть. |
|
Сообщ.
#19
,
|
|
|
|
Esli kod rabotajet, to, mozet, najdetsa u nas blagorodnij perevodchik C++ - VB : )) ?
|
|
Сообщ.
#20
,
|
|
|
|
Не, ну теперь другое дело. Хотя этот метод даст более неточный ответ при достаточно малых или больших х, но всё же он действительно эффективный.
А на счет иррациональных чисел, то так, как ты сказал в школе учат. В теории чисел же любую дробь, где делимое и делитель есть простые число, т.к. существует теорема, что любое алгебраическое выражение может быть представлено в виде дроби с определенной точностью. ![]() ![]() Const eps As Double = 0.000001 Const NMAX As Long = 10000 Function Power(x As Double, y As Double) As Double Dim i As Long Dim kRes As Boolean Dim k As Double, result As Double Do While i < NMAX i = i + 1 k = (i / y - 1) / 2 If Abs(Abs(k) - CLng(Abs(k) + 0.5)) < eps Then kRes = True: Exit Do End If Loop If kRes Then If CLng(i / 2) * 2 = i Then Power = Abs(x) ^ y Else _ Power = -(Abs(x) ^ y) Else Power = 0 'error End If End Function |
|
Сообщ.
#21
,
|
|
|
|
Куллл!!!
Скажи, это ты сам догадался или нашёл где???!!! |
|
Сообщ.
#22
,
|
|
|
|
Цитата Lamerroot от 8.08.04, 14:40 Не, ну теперь другое дело. Хотя этот метод даст более неточный ответ при достаточно малых или больших х, но всё же он действительно эффективный. Ну, вот ! А то сразу с кулаками нападать... A ведь я по сути абсолютно ничего не менял Объясняю тем, кто все же не поял откуда взялся "загадочный" цикл. Пусть x, y вещественные. И пусть x < 0. Тогда по формулам, которые были раньше получаем ( phi_0 = Pi ) x^y = exp( Re( y*( ln(abs(a) + i*phi_0 + 2*k*Pi*i ) ) )* * ( cos( Im( y*( ln(abs(a) + i*phi_0 + 2*k*Pi*i) ) ) + + i* sin( Im( y*( ln(abs(a) + i*phi_0 + 2*k*Pi*i) ) ) ) = = abs(a)^y * ( cos( y*( Pi*( 1 + 2*k ) ) ) + + i* sin( y*( Pi*( 1 + 2*k ) ) ) ) k - любое целое число, т.е. в общем случае имеем бесконечно много значений степени. Но мы хотим выделить только вещественное из всего множества. Для того, чтобы мнимая часть обратилась в ноль, нужно y*( Pi*( 1 + 2*k ) ) = Pi*m, где m - некоторое целое число. Если m - четное, то надо в ответе ставить "+" , если нечетное, то "-". Итак, надо решить задачу. Требуется подобрать такие целые m и k, чтобы удовлетворить равенство y*( 1 + 2*k ) = m Ясно, что, если y = p/q, то решение всегда есть, а поиск знака при степени сводится к анализу делимого на четность, в противном случае решений нет. Но мы хотим, чтобы y было double, это осложняет жизнь, но не сильно. Я выбрал путь изменения m и слежения за k, чтобы сразу затем проверить m. Можно наоборот, и в этом случае не надо делить на y. Что, наверное, более рационально. Насчет того, что называть рациональным числом останусь при своем школьном мнении , т.к. Вы меня не убедили в своей правоте.Цитата Golovastik от 8.08.04, 15:07 Куллл!!! Скажи, это ты сам догадался или нашёл где???!!! ЗЫ. Сам не догадался, а получил, используя минимальные знания ТФКП. Странно, но я раньше не задумывался над тем как возвести отрицательное число в произвольную вещественную степень и можно ли это делать |
|
Сообщ.
#23
,
|
|
|
|
![]() ![]() Странно, но я раньше не задумывался над тем как возвести отрицательное число в произвольную вещественную степень и можно ли это делать Da, zadachka netrivialnaja, no tem i interesnee ejo reshat. Spasibo Math za objasnalku i Lamerroot za perevod |
|
Сообщ.
#24
,
|
|
|
|
Самое приятное в этом , что он умеет и в дробно-отрицательную степень возводить!!!
Калк в винде не умеет в этом смысле НИЧЕГО!!! p.s. thanks |
|
Сообщ.
#25
,
|
|
|
|
ЗЫ. Будте аккуратнее
Эта функция предназначена только для x < 0, для x > 0 она будет глючить, надо использовать обычное возведение в степень |