Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.118.120.204] |
|
Сообщ.
#1
,
|
|
|
В интернете много споров о том, каков должен быть результат вычисления 00 (ноль в нулевой степени).
Одни говорят, что 1, другие, что результат неопределён (NaN). Может быть, сейчас математики уже пришли к какому-то единому мнению? Ну и заодно интересует вопрос возведения нуля в отрицательную степень: каков будет результат в этом случае? |
Сообщ.
#2
,
|
|
|
Самые правильные должны говорить, что "результат неопределён".
Добавлено П.С. ну и ноль в отрицательной - тоже неопределён, но если вы допускаете оперирование с бесконечностью, то можно считать, что равно бесконечности (без знака(!), т.е. знак - неопределён). Добавлено П.П.С. А вообще, помнится, был холивар на близкую тему с Килей, так там результаты были весьма плачевны; ну что-то около того. |
Сообщ.
#3
,
|
|
|
Цитата Славян @ Это как? там результаты были весьма плачевны |
Сообщ.
#4
,
|
|
|
Вообще, в математике это неопределённость.
Если взять две функции g(x) и f(x), такие, что стремятся к нулю при x, стремящемся к 0, то в зависимости от их выбора выражение f(x)g(x) может стремиться к любому значению, от нуля до бесконечности. На практике часто встречается случай, когда обе функции в районе нуля имеют ненулевую производную, то есть ведут себя линейно, в таком случае мы имеем функцию xx, которая стремится к 1. То же верно при выборе любых степеней x. Поэтому при написании библиотек для языков программирования приняли, что 00 = 1. В этом случае в большинстве алгоритмов не приходится делать соответствующую проверку. Хотя в некоторых языках принято, что 00 = 0. Цитата Jin X @ Не вижу никакой логики. Вижу предположение сделанное на основе лишь поверхностного сходства формул.p.s. По мне логика должна быть таковой: если 00=1, то и 0X<0=1, а если 00=NaN, тогда 0X<0=-∞. Попробуй перейти к пределам, тогда поймёшь в чём твоя ошибка. Добавлено Почему пост поменялся без подписи? Цитата Jin X @ Киля упёрся рогом в своё понимание математики, и сдвинуть его с его ошибочной точки зрения никакими доводами не получилось. Это как? |
Сообщ.
#5
,
|
|
|
Цитата amk @ Я тут прогнал немного, удалил уже Не вижу никакой логики. Вижу предположение сделанное на основе лишь поверхностного сходства формул. Добавлено Цитата amk @ Может, всё-таки правильнее возвращать NaN?Поэтому при написании библиотек для языков программирования приняли, что 00 = 1. В этом случае в большинстве алгоритмов не приходится делать соответствующую проверку. Хотя, можно задавать опцию, которая будет определять поведение А что насчёт 0 в отрицательной степени? Или тут тоже всё неоднозначно? Или однозначно? Добавлено Цитата amk @ А результат нуля в отрицательной степени каким приняли возвращать? Поэтому при написании библиотек для языков программирования приняли, что 00 = 1. |
Сообщ.
#6
,
|
|
|
По поводу опции можно сделать, скажем, так.
При X = 0, если опция PowerZeroNaN = True, то: • для Y = 0 результат = NaN • для Y < 0 результат = ∞ А если PowerZeroNaN = False, то: • для Y = 0 результат будет = 1 • для Y < 0 результат = ...???ноль???... |
Сообщ.
#7
,
|
|
|
Вот если сделаете так, как хотите (прогнозируете), то потом этот кусок войдёт в такую-то библиотеку, она - в бо́льшую, та - ещё выше, и (в итоге) народу когда-нибудь выдастся: 2=3. Дотошные пойдут шерстить код, дабы найти коварный изъян, а другие философски скажут "да, мир противоречив" и бардак будет.
|
Сообщ.
#8
,
|
|
|
Славян, я хочу выяснить как лучше (правильнее), только и всего. Так и хочу сделать...
Меня волнуют 00 и 0-1. p.s. По поводу того, что многие возвращают 00=1 я думаю, что смысл тут ещё и в том, что точность хранения вещественного числа конечна и 0 может быть по факту не нулём, а просто очень малым числом, скажем, 10-10000, результат возведения в нулевую степень которого должен дать 0. |
Сообщ.
#9
,
|
|
|
Лучше (и правильнее!) всего - сигнализировать, что "получается особый случай!", а не пытаться его объехать с той или иной долей правды и неправды.
|
Сообщ.
#10
,
|
|
|
Можно сделать так: возвращать результат и флаг корректности.
Если мы возводим отрицательное число в нецелую степень, возвращается NaN и флаг НЕкорректности. Если мы возводим 0 в степень 0, возвращается 1 и флаг НЕкорректности. Если мы возводим 0 в степень < 0, возвращается Inf (или -Inf, если основание = -0) и флаг НЕкорректности. Таким образом, кому нужны значения, могут игнорировать флаг корректности (и даже обрабатывать Inf, а совсем косячные случаи проверять на NaN). |
Сообщ.
#11
,
|
|
|
Древнейший холивар - вот вам дровишек
|
Сообщ.
#12
,
|
|
|
С возвращаемым "флагом корректности" - вполне нормуль! (намёк - хлам в ответе или не хлам ).
|
Сообщ.
#13
,
|
|
|
Цитата Славян @ Ну да. Если хлам, то там может быть либо 1, либо Inf, либо NaN намёк - хлам в ответе или не хлам |
Сообщ.
#14
,
|
|
|
Проще сделать не флаг, который придётся проверять, а две функции с разным поведением в этой ситуации.
Цитата Jin X @ для Y < 0 результат = ∞ Цитата Jin X @ Говорю же: не вижу логики, а лишь догадки. Поскольку тут однозначно должна быть +∞ (в случае X=+0) и NaN в случае X=-0, никакой неопределённости в этом случае нет.для Y < 0 результат = ...???ноль???... Случай Y=-0, кстати, тоже должен рассматриваться как Y<0. |
Сообщ.
#15
,
|
|
|
Цитата amk @ Речь идёт только про X=0 ?Случай Y=-0, кстати, тоже должен рассматриваться как Y<0. Правильно ли я пишу: Результат операции 00 не определён, однако многие программные библиотеки возвращают 1. Почему? Видимо, это связано во-первых, с возможной погрешностью вычислений, в результате которых 0 может быть по факту совсем не нулём, а очень малым числом (скажем, 10-10000, но мы получим ноль, поскольку разрядность мантиссы и показателя степени при хранении чисел с плавающей запятой конечны и обычно не очень велики), соответственно, нулевая степень такого числа должна быть равна 1. Во-вторых, это может быть связано с интегральными исчислениями, когда имеются функции f(x) и g(x), стремящиеся к нулю при x->0, но имеющие ненулевые производные, поэтому и результат вычисления f(x)g(x) должен быть определён (и обычно он стремится к 1). Добавлено Цитата amk @ Можно сделать с флагом и 2 обёртки: которая ругается на 00 и которая хавает.Проще сделать не флаг, который придётся проверять, а две функции с разным поведением в этой ситуации. Более того, можно сделать не флаг, а код корректности: 0 – корректный результат 1 – 0 в степени 0, результат = 1 (по правилам математики должен быть не определён, однако основание X = 0, переданное функции может являться результатом округления близкого к 0 числа (например, 10^-10000), тогда результатом возведения такого числа в степень 0 должна быть 1, поэтому оставим эту неоднозначную ситуацию на усмотрение программиста) 2 – 0 в отрицательной степени, результат = бесконечности (Inf) 3 – слишком большой по модулю результат (бесконечность, +/-Inf) 4 – попытка возвести отрицательное число в нецелую степень, либо X или Y = NaN, результат - нечисло (QNaN) Добавлено Цитата amk @ Почему NaN? Может, если степень целая, то тоже Inf (и -Inf при нечётной степени)? NaN в случае X=-0, никакой неопределённости в этом случае нет. |
Сообщ.
#16
,
|
|
|
Не пойму, что вы спорите. Любое число в нулевой степени равно 1 – это пошло как следствие из формулы частного степеней с одинаковым основанием: x0 = xa-a = xa/xa = 1. И как ни странно, строго она легко доказывается через пределы. Т.к. 00 по факту ведёт к неопределённости 0/0, то NaN, и дело с концом.
P.S. Кому как не тебе, Jin X, знать, что делает FPU с неопределённым результатом, если ему замаскировать #IA и если не маскировать. |
Сообщ.
#17
,
|
|
|
Цитата Jin X @ В целом правильно. Ты повторил то, что я выше написал. Но не рассмотрел некоторых ситуаций.Правильно ли я пишу: Так, основание может стремиться к нулю быстрее показателя, тогда предел сойдётся к нулю, а не к единице. Подобрав пару функций, можно добиться предела, равного любому числу от 0 до ∞. Цитата Jin X @ Оба варианта не комильфо,Можно сделать с флагом и 2 обёртки: которая ругается на 00 и которая хавает. Более того, можно сделать не флаг, а код корректности: Установка флага, и потом проверка его в обёртке - это всё-таки лишние телодвижения, причём не являющиеся необходимыми, в то время как две отдельно реализованные функции (возможно с общей вычислительной частью) обойдутся у\куда дешевле. И это не будет преждевременной оптимизацией, при написании библиотек действуют несколько другие правила разработки. Так в математических библиотеках как правило есть функции log(x) и log10(x), а часто ещё и log2(x) и log(x, b), хотя казалось бы хватило и одной из них. Просто набор из таких функций можно реализовать эффективнее, чем одну универсальную функцию. И программы от этого становятся несколько читабельнее. Код корректности здесь не годится по той же причине, если тебе надо как-то выделить случай X,Y=0, то гораздо читабельнее непосредственно проверить эти значения, чем после вызова функции (!) анализировать какой-то флаг. Не забывай, функцию ты вызываешь внутри какого-то выражения, от того, что ты каждую функцию будешь вызывать по отдельности, и что-то анализировать программа просто перестанет читаться. Или тебе придётся каждый раз писать для неё обёртку, анализирующую этот код завершения. кончится тем, что ты эту обёртку будешть втыкать во все проекты и забудешь про библиотечную функцию с таким нелепым интерфейсом. Код завершения уместен при вызове процедуры, реализующих какой-либо сложный алгоритм, или при вызове функции-фабрики (это я про fopen из C), которые и так обычно вызываются отдельно. И то, в последнем варианте j,sxyj возвращают значение, что что-то пошло не так, а ошибку фиксируют другим способом. Добавлено Qraizer, большинство математических библиотек возвращают в этом случае всё-же 1, потому как должны работать и с не IEEE-представлениями чисел с плавающей точкой, в которых нет NaN или ±inf. |
Сообщ.
#18
,
|
|
|
Цитата amk @ Это оправдано, ибо Ln, Lg и Log2 – очень примитивные функции и отличаются 1 инструкцией (из 2-3-х), которая и определяет основание логарифма.log(x) и log10(x), а часто ещё и log2(x) и log(x, b) Здесь же обёртки очень простые (и они могут быть inline-овыми), а основная функция с кодом результата – это и есть "общая вычислительная часть", которая в сравнении с логарифмами довольно громоздкая. А так вообще, конечно, можно подумать на предмет усложнения и упрощения... ибо я не очень уверен, что разделение результата вычисления в зависимости от знака нуля вообще нужнО. Цитата amk @ Здесь всё зависит от задачи. Одно дело, когда это функция внутри сложного выражения, другое, когда она, например, внутри калькулятора (анализатора текстовой формулы), где можно играться с этим кодом без проблем.Не забывай, функцию ты вызываешь внутри какого-то выражения, от того, что ты каждую функцию будешь вызывать по отдельности, и что-то анализировать программа просто перестанет читаться. Вообще, задумка такая: unit Power7x; interface var PowerNormalResultLevel: Integer = 1; // Допустимый уровень результата, возвращаемый функциями FastPower (без параметра Correct), выше которого генерируется исключение const // Коды корректности результата вычисления степени функцией FastPower fprOK = 0; // Корректный результат fpr00 = 1; // 0 в степени 0, результат = 1 (если вы хотите, чтобы результат был не определён, проверяйте этот код либо установите PowerNormalResultLevel = 0 и используйте FastPower без параметра Correct) :) fpr0Neg = 2; // 0 в отрицательной степени, результат = бесконечности (Inf) fprInf = 3; // Слишком большой по модулю результат (бесконечность, +/-Inf) fprNaN = 4; // Попытка возвести отрицательное число в нецелую степень, либо X или Y = NaN, результат - нечисло (QNaN) // Возведение X в степень Y // Возвращает результат возведения в степень, а в переменную Correct записывается код корректности результата (см. fprXXX) function FastPower(const X, Y: Single; out Correct: Integer): Single; overload; function FastPower(const X, Y: Double; out Correct: Integer): Double; overload; function FastPower(const X, Y: Extended; out Correct: Integer): Extended; overload; // Возведение X в степень Y // Возвращает результат возведения в степень, осуществляет проверку корректности результата и генерирует исключение, если результат превышает значение переменной PowerNormalResultLevel function FastPower(const X, Y: Single): Single; overload; function FastPower(const X, Y: Double): Double; overload; function FastPower(const X, Y: Extended): Extended; overload; // Возведение X в степень Y // Возвращает результат возведения в степень, осуществляет проверку корректности результата и генерирует исключение, если результат превышает значение переменной ResultLevel function FastPowerChk(const X, Y: Single; ResultLevel: Integer): Single; overload; function FastPowerChk(const X, Y: Double; ResultLevel: Integer): Double; overload; function FastPowerChk(const X, Y: Extended; ResultLevel: Integer): Extended; overload; // Возведение X в степень Y // Возвращает код корректности результата, а результат возведения в степень записывает в переменную Z function FastPowerCode(const X, Y: Single; out Z: Single): Integer; overload; function FastPowerCode(const X, Y: Double; out Z: Double): Integer; overload; function FastPowerCode(const X, Y: Extended; out Z: Extended): Integer; overload; // Проверка числа на корректность (возвращает False, если число является Inf или NaN) function IsNormal(const X: Single): Boolean; overload; function IsNormal(const X: Double): Boolean; overload; function IsNormal(const X: Extended): Boolean; overload; implementation end. Уверен, можно улучшить (т.к. не шибко долго думал над тем, как это лучше сделать), но пока так... Добавлено Чем мне не нравится Power от Delphi (Math.pas)? Как минимум из-за того, что если X < 0, а Y целый и > MaxInt, то он почему-то думает, что Y нецелый... Да и к тому же, свой число asm-овский вариант хочу сделать... У меня уже даже есть код, но вот надо решить вопрос с этим нулём. Добавлено Представьте себе, этот косяк присутствует и в D7, и в Tokyo. Ну и можно кое-какие другие моменты соптимизировать... в частности обойтись без очень медленной sahf. Это всё 32 бита... А вот с 64 битами, конечно, посложнее Добавлено Тут, конечно, с генерацией исключений надо подумать... потому что есть уже настроенный вариант (маска исключений), который трогать нет смысла. В общем, я подумаю, как сделать, чтобы не было такого большого кол-ва функций, лишних обёрток с искусственной генерацией исключений и пр. Добавлено Наверное, amk прав. Лучше сделать 2 функции... но флаг корректности всё равно нужен, чтобы в случае замаскированных исключений можно было проверить результат... В ассемблере с этим удобнее, конечно: можно возвращать результат и в st(0), и в AL (сразу)... или во флаг CF, скажем |
Сообщ.
#19
,
|
|
|
Цитата amk @ Не-а, не поэтому. Ты назвал настоящую причину: lim xx при x→0 сходится к 1. Но коли ты упомянул IEEE, то тем более не понимаю, зачем пытаться оспаривать стандарт. Он основан на строгих матִͺправилах.Qraizer, большинство математических библиотек возвращают в этом случае всё-же 1, потому как должны работать и с не IEEE-представлениями чисел с плавающей точкой, в которых нет NaN или ±inf. Другое дело, что Jin X-у захотелось универсализировать свою функцию. Ну так так бы и сказал, зачем было так странно формулировать вопрос темы. Цитата Jin X @ Ужас. Жирный интерфейс у такой простой задачи. У Дельфей вроде есть шаблоны. На них понятие политики поведения можно реализовать? Вообще, задумка такая: ... |
Сообщ.
#20
,
|
|
|
Qraizer, мне захотелось её сделать правильной, в первую очередь. Ну и даль возможность по-разному реагировать на "особые случаи"...
Добавлено Цитата Qraizer @ Я согласен, что жирный, упрощу.Жирный интерфейс у такой простой задачи. У Дельфей вроде есть шаблоны. На них понятие политики поведения можно реализовать? Шаблоны работают только для классов, да и появились они в D2009 (вместе с Unicode по дефолту), а людей, пользующихся D7 или D2007 довольно много. К тому же, для Single/Double/Extended это всё не подойдёт, т.к. там должна идти работа с экспонентной частью, которая своя у каждого типа... |
Сообщ.
#21
,
|
|
|
Вот так, думаю, будет нормально...
Да, тоже много всего, но основных функций всего 3 (+2 перегруженные). IsNormal, FloatValueType и FloatValueTypeEx – уже не относящиеся к степени функции, чисто вспомогательные. unit Power7x; {$IF CompilerVersion >= 17} // Delphi 2005+ {$DEFINE INLINE} {$IFEND} interface const // Коды корректности результата вычисления степени функцией FastPowerNX fprOK = 0; // Корректный результат fpr00 = 1; // 0 в степени 0, результат = 1 (если вы хотите, чтобы результат был не определён, проверяйте этот код) :) fpr0Neg = 2; // 0 в отрицательной степени, результат = бесконечности fprInf = 3; // Слишком большой по модулю результат (бесконечность) fprNaN = 4; // Попытка возвести отрицательное число в нецелую степень, либо X или Y = NaN, результат - нечисло (NaN) type // Тип значения вещественного числа (нормальное, бесконечность, нечисло) TFloatValueType = (fvNormal, fvInfinity, fvNaN); // Расширенный тип значения вещественного числа (нормализованное положительное и отрицательное, денормализованное // положительное и отрицательное, ноль и отрицательный ноль, плюс и минус бесконечность, нечисло QNaN и SNaN) TFloatValueTypeEx = (fvxPosNormal, fvxNegNormal, fvxPosDenormal, fvxNegDenormal, fvxZero, fvxNegZero, fvxPosInfinity, fvxNegInfinity, fvxQNaN, fvxSNaN); // Тип функции возведения в степень (FastPower или FastPower0N) TFastPowerFunc = function(const X, Y: Extended): Extended; // Тип функции быстрого возведения в целую степень (FastIntPower или FastIntPower0N) TFastIntPowerFunc = function(const X: Extended; Y: Integer): Extended; /////////////////////////////////////////// // ОСНОВНЫЕ ФУНКЦИИ ВОЗВЕДЕНИЯ В СТЕПЕНЬ // /////////////////////////////////////////// // Возведение X в степень Y (0^0 возвращает как 1) function FastPower(const X, Y: Extended): Extended; // Возведение X в степень Y (0^0 возвращает как NaN) function FastPower0N(const X, Y: Extended): Extended; // Если вам необходимо использовать функцию FastPower или FastPowerN0 в зависимости от ситуации (например, согласно настройкам), // вы можете присвоить указатель на одну из этих функций переменной FastPowerFunc и использовать её вместо этих функции. var FastPowerFunc: TFastPowerFunc = FastPower; // Возведение X в степень Y (0^0 возвращает как 1) // Предотвращает генерацию исключений, возвращая код корректности результата в переменную Correct (см. fprXXX) function FastPowerNX(const X, Y: Single; out Correct: Integer): Single; overload; function FastPowerNX(const X, Y: Double; out Correct: Integer): Double; overload; function FastPowerNX(const X, Y: Extended; out Correct: Integer): Extended; overload; //////////////////////////////////////////////// // БЫСТРЫЕ ФУНКЦИИ ВОЗВЕДЕНИЯ В ЦЕЛУЮ СТЕПЕНЬ // //////////////////////////////////////////////// // Быстрое возведение X в целую степень Y (0^0 возвращает как 1) function FastIntPower(const X: Extended; Y: Integer): Extended; // Быстрое возведение X в целую степень Y (0^0 возвращает как NaN) function FastIntPower0N(const X: Extended; Y: Integer): Extended; // Если вам необходимо использовать функцию FastIntPower или FastIntPowerN0 в зависимости от ситуации (например, согласно настройкам), // вы можете присвоить указатель на одну из этих функций переменной FastIntPowerFunc и использовать её вместо этих функции. var FastIntPowerFunc: TFastIntPowerFunc = FastIntPower; // Быстрое возведение X в целую степень Y (0^0 возвращает как 1) // Предотвращает генерацию исключений, возвращая код корректности результата в переменную Correct (см. fprXXX) function FastIntPowerNX(const X: Single; Y: Integer; out Correct: Integer): Single; overload; function FastIntPowerNX(const X: Double; Y: Integer; out Correct: Integer): Double; overload; function FastIntPowerNX(const X: Extended; Y: Integer; out Correct: Integer): Extended; overload; ///////////////////////////// // ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ // ///////////////////////////// // Проверка числа на корректность (возвращает False, если число = бесконечности или NaN) function IsNormal(const X: Single): Boolean; overload; function IsNormal(const X: Double): Boolean; overload; function IsNormal(const X: Extended): Boolean; overload; // Получение типа значения вещественного числа function FloatValueType(const X: Single): TFloatValueType; overload; function FloatValueType(const X: Double): TFloatValueType; overload; function FloatValueType(const X: Extended): TFloatValueType; overload; // Получение расширенного типа значения вещественного числа function FloatValueTypeEx(const X: Single): TFloatValueTypeEx; overload; function FloatValueTypeEx(const X: Double): TFloatValueTypeEx; overload; function FloatValueTypeEx(const X: Extended): TFloatValueTypeEx; overload; implementation end. |
Сообщ.
#22
,
|
|
|
Кстати, неплохо бы, чтобы кто-то у вас вычислял -32-0.2, а то как-то натыкался, что стандартные вываливались с ошибкой...
Добавлено Имелось ввиду: (-32)-1/5 |
Сообщ.
#23
,
|
|
|
Ну, если правильной, то только два варианта: либо нуль рассматривается как бесконечно малое, либо как нуль. В качестве маскированной реакции первое, в качестве сигнализирующей – второе.
В C некоторые реализации RTL для этого предусматривают специальную функцию _matherr(), которая вызывается при всех математических ошибках. Пользоваться ею не шибко удобно, но в своё время всех устраивало. Чиста по-паскалевски если, можно предусмотреть callback-функцию, которую можно получить/установить парой get...()/set...() функций из твоего модуля. Кому надо, пусть ставят свой обработчик, и нехай он делает, что им надо. Бросает какое-нибудь исключение, например. Или возвращает некое данное, например то же NaN(). В общем, пусть сами решают, как обработчик писать. Дефолтовый же обработчик пусть обрабатывает ситуацию как маскированную реакцию. P.S. Цитата Jin X @ Та я не о параметризации типов, я о параметризации поведения. Я уже вспомнил, что шаблоны там простенькие, обычные дженерики, и то не факт, что сопоставимые с дженериками в других языках.Шаблоны работают только для классов, да и появились они в D2009 (вместе с Unicode по дефолту), а людей, пользующихся D7 или D2007 довольно много. К тому же, для Single/Double/Extended это всё не подойдёт, т.к. там должна идти работа с экспонентной частью, которая своя у каждого типа... Просто на Плюсах можно было бы вынести реакцию на спец.ситуации в отдельный класс и передавать его шаблонным параметром. Написать две/три готовых стратегий поведения прям в твоём модуле, а кому мало, может и свои написать. В принципе, в таком классе достаточно было бы иметь всего один метод, по-разному реализованный в разных стратегиях, а твои Power() могут просто звать этот метод той стратегии, которая им передана и не заморачиваться больше ничем. Получилось бы что-то типа: namespace Power { // стратегии template <typename T> struct ReturnOne { static T matherr(T, T) { return static_cast<T>(1); } }; template <typename T> struct ReturnNaN { static T matherr(T, T) { return std::numeric_limits<T>::quiet_NaN(); } }; template <typename T> struct Throw { static T matherr(T l, T r) { return std::runtime_error(static_cast<std::ostringstream&>(std::ostringstream() << std::dec << "Indefinite result for " << l << " and " << r << " params").str()); } }; // функция template <typename T, template <typename> class Err = ReturnOne> T power(T l, T r, Err) { if (/* ... */) return Err<T>::matherr(l, r); /* ... */ } } |
Сообщ.
#24
,
|
|
|
Цитата Славян @ Ответ будет 5.66*i, это комплексные числа.Имелось ввиду: (-32)-1/5 Цитата Qraizer @ Зачем такой заморочь, когда программист просто может написать обёртку, которая будет вызывать нашу функцию и проверять результат (код корректности), в зависимости от которого делать что надо. Единственное, так будет чуть медленнее, т.к. здесь обёртка будет делать лишний вызов и сравнение, а callback – только в случае. Но это надо ещё одну функцию создавать типаЧиста по-паскалевски если, можно предусмотреть callback-функцию, которую можно получить/установить парой get...()/set...() функций из твоего модуля. Кому надо, пусть ставят свой обработчик, и нехай он делает, что им надо. Бросает какое-нибудь исключение, например. Или возвращает некое данное, например то же NaN(). В общем, пусть сами решают, как обработчик писать type TFastPowerErrorCallback = function(const Value: Extended; Code, Tag: Integer); function FastPowerECB(const X, Y: Extended; ErrorCallback: TFastPowerErrorCallback; Tag: Integer = 0): Extended; Цитата Qraizer @ К сожалению, C++ знаю плохо, не понимаю фишки Получилось бы что-то типа: Добавлено Вот так: type // Тип callback-функции для функций FastPowerECB и FastIntPowerECB, вызывается в случае возникновения ошибки/неоднозначной ситуации // Value - результат, который вернула бы функция FastPowerNX, Code - код корректности результата, Tag - пользовательское значение // Не сравнивайте значение Value с каким-либо другим, т.к. значение Inf или NaN вызовет исключение (при стадартных настройках со-процессора в Delphi), // используйте для проверки значение Code или функции IsNormal, FloatValueType, FloatValueTypeEx TFastPowerErrorCallback = function(const Value: Extended; Code, Tag: Integer); // Возведение X в степень Y // Предотвращает генерацию исключений; в случае возникновения ошибки/неоднозначной ситуации вызывается функция Callback, результат которой и возвращается function FastPowerECB(const X, Y: Extended; Callback: TFastPowerErrorCallback; Tag: Integer = 0): Extended; // Быстрое возведение X в целую степень Y // Предотвращает генерацию исключений; в случае возникновения ошибки/неоднозначной ситуации вызывается функция Callback, результат которой и возвращается function FastIntPowerECB(const X: Extended; Y: Integer; Callback: TFastPowerErrorCallback; Tag: Integer = 0): Extended; |
Сообщ.
#25
,
|
|
|
Цитата Jin X @ Эх, а я надеялся всё же увидеть ответ -0,5. Цитата Славян @ Ответ будет 5.66*i, это комплексные числа.Имелось ввиду: (-32)-1/5 |
Сообщ.
#26
,
|
|
|
Цитата Славян @ Ой, почему-то вычислял (-32)-0.5, а тут (-32)-1/5=0.5i будет.Эх, а я надеялся всё же увидеть ответ -0,5. А чтобы получилось -0.5, можно сделать так: -(32-1/5) Если я всё правильно понимаю... |
Сообщ.
#27
,
|
|
|
Э, нет! Суть именно в том, чтобы из отрицательного взять отрицательную степень и получить нормальный (вещественный) ответ, а не хитрить.
Добавлено Впрочем, можно отмазаться, если -0,2 не представимо точно в FPU (не знаю, не вникал). Но всё равно, подобрать когда всё представимо, думаю, можно попробовать. |
Сообщ.
#28
,
|
|
|
Можно сделать так: sqrt(-5)*sqrt(-5) = -5
|
Сообщ.
#29
,
|
|
|
Цитата Jin X @ Ответ будет 5.66*i, это комплексные числа. откуда комплексные числа? ответ будет = 1/(корень 5 степени из -32) = -0,5 Добавлено сорри, уже насчитали))) |
Сообщ.
#30
,
|
|
|
Цитата JoeUser @ Ты про что? Ответ какого выражения? ответ будет = 1/(корень 5 степени из -32) = -0,5 |
Сообщ.
#31
,
|
|
|
Цитата Славян @ Наверное не представимо. Там всё - степени двояков, т.е. чётные, так что подобрать честные данные для эксперимента не получится, мыслится мне. если -0,2 не представимо точно в FPU (не знаю, не вникал). Но всё равно, подобрать когда всё представимо, думаю, можно попробовать. |
Сообщ.
#32
,
|
|
|
Цитата Jin X @ Ты про что? Ответ какого выражения? -32 в степени -0.2 Добавлено Кстати, JavaScript тоже косячит со своим Math.pow(-32.0,-0.2), возвращает NaN, надо хелпер писать для таких случаев, разбирать четность корня при отрицательной базе Добавлено А вот Perl - кросава!!! print -32.0**-0.2; |
Сообщ.
#33
,
|
|
|
Действительно - красавцы!
Добавлено Эй, а там всё же скобки надо, а? |
Сообщ.
#34
,
|
|
|
Цитата Славян @ Эй, а там всё же скобки надо, а? Неа, там ** - это оператор степени. |
Сообщ.
#35
,
|
|
|
И что? Он же "-" у 32 опосля степени возьмёт, небось!
Добавлено Унарный минус менее важен, нежели степень (в математике), а потому сочтёт как "-(32**-0.2)". Так? |
Сообщ.
#36
,
|
|
|
У него приоритет ниже чем у отрицания, он выполнится после остальных.
|
Сообщ.
#37
,
|
|
|
Кто "он", у кого "него"? У неё, у степени? Короче, со скобками проверить будет понадёжнее: "(-32)**-0.2".
|
Сообщ.
#38
,
|
|
|
Ну него - оператора степени.
|
Сообщ.
#39
,
|
|
|
Ясно. Странно, но ладно.
Добавлено Хм, получается, что на выражение "2**4-2**3" он должен вывалиться с ошибкой, т.к., анализируя "**3", увидел, что берётся степень у "-2", а потом приклеивается результат к другому выражению? Вместо рационального вычисления 24-23. |
Сообщ.
#40
,
|
|
|
Нет. Перл это выражение посчитает как 8, т.к. в данном выражении "-" это не унарный минус, а оператор "вычитание".
А вот в таком "2**4**-2**3" это будет унарный минус, и будет последовательное возведение в степень. |
Сообщ.
#41
,
|
|
|
PHP на -32**-0.5 выдаёт 0.5, а вот на (-32)**-0.5 выдаёт NAN... А Perl?
А вообще, Википедия говорит, что "Корень нечётной степени из отрицательного числа — отрицательное число, однозначно определенное" Т.е. получается, что действительно (-32)-0.2=-0.5. |
Сообщ.
#42
,
|
|
|
Цитата Jin X @ Joe уверяет, что всё норм:А Perl? Цитата JoeUser @ Там, правда, без скобок -32, но уверяет, что Перл схавает вначале -32, а потом ужо пойдёт степень брать. Я не проверял-с. А вот Perl - кросава!!! |
Сообщ.
#43
,
|
|
|
Цитата Славян @ Без скобок и PHP нормально выводит... Там, правда, без скобок -32 |