На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! правила раздела Алгоритмы
1. Помните, что название темы должно хоть как-то отражать ее содержимое (не создавайте темы с заголовком ПОМОГИТЕ, HELP и т.д.). Злоупотребление заглавными буквами в заголовках тем ЗАПРЕЩЕНО.
2. При создании темы постарайтесь, как можно более точно описать проблему, а не ограничиваться общими понятиями и определениями.
3. Приводимые фрагменты исходного кода старайтесь выделять тегами code.../code
4. Помните, чем подробнее Вы опишете свою проблему, тем быстрее получите вразумительный совет
5. Запрещено поднимать неактуальные темы (ПРИМЕР: запрещено отвечать на вопрос из серии "срочно надо", заданный в 2003 году)
6. И не забывайте о кнопочках TRANSLIT и РУССКАЯ КЛАВИАТУРА, если не можете писать в русской раскладке :)
Модераторы: Akina, shadeofgray
  
> Степени нуля
    В интернете много споров о том, каков должен быть результат вычисления 00 (ноль в нулевой степени).
    Одни говорят, что 1, другие, что результат неопределён (NaN).
    Может быть, сейчас математики уже пришли к какому-то единому мнению?

    Ну и заодно интересует вопрос возведения нуля в отрицательную степень: каков будет результат в этом случае?
    Сообщение отредактировано: Jin X -
      Самые правильные должны говорить, что "результат неопределён". :yes:

      Добавлено
      П.С. ну и ноль в отрицательной - тоже неопределён, но если вы допускаете оперирование с бесконечностью, то можно считать, что равно бесконечности (без знака(!), т.е. знак - неопределён).

      Добавлено
      П.П.С. А вообще, помнится, был холивар на близкую тему с Килей, так там результаты были весьма плачевны; ну что-то около того. :blush:
        Цитата Славян @
        там результаты были весьма плачевны
        Это как? :)
          Вообще, в математике это неопределённость.
          Если взять две функции 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 @
          Это как?
          Киля упёрся рогом в своё понимание математики, и сдвинуть его с его ошибочной точки зрения никакими доводами не получилось.
            Цитата amk @
            Не вижу никакой логики. Вижу предположение сделанное на основе лишь поверхностного сходства формул.
            Я тут прогнал немного, удалил уже :)

            Добавлено
            Цитата amk @
            Поэтому при написании библиотек для языков программирования приняли, что 00 = 1. В этом случае в большинстве алгоритмов не приходится делать соответствующую проверку.
            Может, всё-таки правильнее возвращать NaN?
            Хотя, можно задавать опцию, которая будет определять поведение :)
            А что насчёт 0 в отрицательной степени? Или тут тоже всё неоднозначно? Или однозначно? :)

            Добавлено
            Цитата amk @
            Поэтому при написании библиотек для языков программирования приняли, что 00 = 1.
            А результат нуля в отрицательной степени каким приняли возвращать?
              По поводу опции можно сделать, скажем, так.
              При X = 0, если опция PowerZeroNaN = True, то:
              • для Y = 0 результат = NaN
              • для Y < 0 результат = ∞
              А если PowerZeroNaN = False, то:
              • для Y = 0 результат будет = 1
              • для Y < 0 результат = ...???ноль???...
                Вот если сделаете так, как хотите (прогнозируете), то потом этот кусок войдёт в такую-то библиотеку, она - в бо́льшую, та - ещё выше, и (в итоге) народу когда-нибудь выдастся: 2=3. Дотошные пойдут шерстить код, дабы найти коварный изъян, а другие философски скажут "да, мир противоречив" и бардак будет. :yes-sad:
                  Славян, я хочу выяснить как лучше (правильнее), только и всего. Так и хочу сделать...
                  Меня волнуют 00 и 0-1.

                  p.s. По поводу того, что многие возвращают 00=1 я думаю, что смысл тут ещё и в том, что точность хранения вещественного числа конечна и 0 может быть по факту не нулём, а просто очень малым числом, скажем, 10-10000, результат возведения в нулевую степень которого должен дать 0.
                    Лучше (и правильнее!) всего - сигнализировать, что "получается особый случай!", а не пытаться его объехать с той или иной долей правды и неправды.
                      Можно сделать так: возвращать результат и флаг корректности.
                      Если мы возводим отрицательное число в нецелую степень, возвращается NaN и флаг НЕкорректности.
                      Если мы возводим 0 в степень 0, возвращается 1 и флаг НЕкорректности.
                      Если мы возводим 0 в степень < 0, возвращается Inf (или -Inf, если основание = -0) и флаг НЕкорректности.
                      Таким образом, кому нужны значения, могут игнорировать флаг корректности (и даже обрабатывать Inf, а совсем косячные случаи проверять на NaN).
                        Древнейший холивар - вот вам дровишек :)
                          С возвращаемым "флагом корректности" - вполне нормуль! (намёк - хлам в ответе или не хлам :whistle: ).
                            Цитата Славян @
                            намёк - хлам в ответе или не хлам
                            Ну да. Если хлам, то там может быть либо 1, либо Inf, либо NaN :)
                              Проще сделать не флаг, который придётся проверять, а две функции с разным поведением в этой ситуации.
                              Цитата Jin X @
                              для Y < 0 результат = ∞

                              Цитата Jin X @
                              для Y < 0 результат = ...???ноль???...
                              Говорю же: не вижу логики, а лишь догадки. Поскольку тут однозначно должна быть +∞ (в случае X=+0) и NaN в случае X=-0, никакой неопределённости в этом случае нет.
                              Случай Y=-0, кстати, тоже должен рассматриваться как Y<0.
                                Цитата amk @
                                Случай Y=-0, кстати, тоже должен рассматриваться как Y<0.
                                Речь идёт только про X=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 в случае X=-0, никакой неопределённости в этом случае нет.
                                Почему NaN? Может, если степень целая, то тоже Inf (и -Inf при нечётной степени)?
                                  Не пойму, что вы спорите. Любое число в нулевой степени равно 1 – это пошло как следствие из формулы частного степеней с одинаковым основанием: x0 = xa-a = xa/xa = 1. И как ни странно, строго она легко доказывается через пределы. Т.к. 00 по факту ведёт к неопределённости 0/0, то NaN, и дело с концом.

                                  P.S. Кому как не тебе, Jin X, знать, что делает FPU с неопределённым результатом, если ему замаскировать #IA и если не маскировать.
                                  Сообщение отредактировано: Qraizer -
                                    Цитата 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.
                                      Цитата amk @
                                      log(x) и log10(x), а часто ещё и log2(x) и log(x, b)
                                      Это оправдано, ибо Ln, Lg и Log2 – очень примитивные функции и отличаются 1 инструкцией (из 2-3-х), которая и определяет основание логарифма.
                                      Здесь же обёртки очень простые (и они могут быть inline-овыми), а основная функция с кодом результата – это и есть "общая вычислительная часть", которая в сравнении с логарифмами довольно громоздкая.
                                      А так вообще, конечно, можно подумать на предмет усложнения и упрощения... ибо я не очень уверен, что разделение результата вычисления в зависимости от знака нуля вообще нужнО.

                                      Цитата amk @
                                      Не забывай, функцию ты вызываешь внутри какого-то выражения, от того, что ты каждую функцию будешь вызывать по отдельности, и что-то анализировать программа просто перестанет читаться.
                                      Здесь всё зависит от задачи. Одно дело, когда это функция внутри сложного выражения, другое, когда она, например, внутри калькулятора (анализатора текстовой формулы), где можно играться с этим кодом без проблем.
                                      Вообще, задумка такая:
                                      ExpandedWrap disabled
                                        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, скажем :)
                                        Цитата amk @
                                        Qraizer, большинство математических библиотек возвращают в этом случае всё-же 1, потому как должны работать и с не IEEE-представлениями чисел с плавающей точкой, в которых нет NaN или ±inf.
                                        Не-а, не поэтому. Ты назвал настоящую причину: lim xx при x→0 сходится к 1. Но коли ты упомянул IEEE, то тем более не понимаю, зачем пытаться оспаривать стандарт. Он основан на строгих матִͺправилах.
                                        Другое дело, что Jin X-у захотелось универсализировать свою функцию. Ну так так бы и сказал, зачем было так странно формулировать вопрос темы.
                                        Цитата Jin X @
                                        Вообще, задумка такая:
                                        ...
                                        Ужас. Жирный интерфейс у такой простой задачи. У Дельфей вроде есть шаблоны. На них понятие политики поведения можно реализовать?
                                        Сообщение отредактировано: Qraizer -
                                          Qraizer, мне захотелось её сделать правильной, в первую очередь. Ну и даль возможность по-разному реагировать на "особые случаи"...

                                          Добавлено
                                          Цитата Qraizer @
                                          Жирный интерфейс у такой простой задачи. У Дельфей вроде есть шаблоны. На них понятие политики поведения можно реализовать?
                                          Я согласен, что жирный, упрощу.
                                          Шаблоны работают только для классов, да и появились они в D2009 (вместе с Unicode по дефолту), а людей, пользующихся D7 или D2007 довольно много. К тому же, для Single/Double/Extended это всё не подойдёт, т.к. там должна идти работа с экспонентной частью, которая своя у каждого типа...
                                            Вот так, думаю, будет нормально...
                                            Да, тоже много всего, но основных функций всего 3 (+2 перегруженные).
                                            IsNormal, FloatValueType и FloatValueTypeEx – уже не относящиеся к степени функции, чисто вспомогательные.
                                            ExpandedWrap disabled
                                              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.
                                              Кстати, неплохо бы, чтобы кто-то у вас вычислял -32-0.2, а то как-то натыкался, что стандартные вываливались с ошибкой...

                                              Добавлено
                                              Имелось ввиду: (-32)-1/5
                                                Ну, если правильной, то только два варианта: либо нуль рассматривается как бесконечно малое, либо как нуль. В качестве маскированной реакции первое, в качестве сигнализирующей – второе.
                                                В C некоторые реализации RTL для этого предусматривают специальную функцию _matherr(), которая вызывается при всех математических ошибках. Пользоваться ею не шибко удобно, но в своё время всех устраивало. Чиста по-паскалевски если, можно предусмотреть callback-функцию, которую можно получить/установить парой get...()/set...() функций из твоего модуля. Кому надо, пусть ставят свой обработчик, и нехай он делает, что им надо. Бросает какое-нибудь исключение, например. Или возвращает некое данное, например то же NaN(). В общем, пусть сами решают, как обработчик писать. Дефолтовый же обработчик пусть обрабатывает ситуацию как маскированную реакцию.

                                                P.S.
                                                Цитата Jin X @
                                                Шаблоны работают только для классов, да и появились они в D2009 (вместе с Unicode по дефолту), а людей, пользующихся D7 или D2007 довольно много. К тому же, для Single/Double/Extended это всё не подойдёт, т.к. там должна идти работа с экспонентной частью, которая своя у каждого типа...
                                                Та я не о параметризации типов, я о параметризации поведения. Я уже вспомнил, что шаблоны там простенькие, обычные дженерики, и то не факт, что сопоставимые с дженериками в других языках.
                                                Просто на Плюсах можно было бы вынести реакцию на спец.ситуации в отдельный класс и передавать его шаблонным параметром. Написать две/три готовых стратегий поведения прям в твоём модуле, а кому мало, может и свои написать. В принципе, в таком классе достаточно было бы иметь всего один метод, по-разному реализованный в разных стратегиях, а твои Power() могут просто звать этот метод той стратегии, которая им передана и не заморачиваться больше ничем.
                                                Получилось бы что-то типа:
                                                ExpandedWrap disabled
                                                  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);
                                                    /* ... */
                                                  }
                                                   
                                                  }
                                                Сообщение отредактировано: Qraizer -
                                                  Цитата Славян @
                                                  Имелось ввиду: (-32)-1/5
                                                  Ответ будет 5.66*i, это комплексные числа.

                                                  Цитата Qraizer @
                                                  Чиста по-паскалевски если, можно предусмотреть callback-функцию, которую можно получить/установить парой get...()/set...() функций из твоего модуля. Кому надо, пусть ставят свой обработчик, и нехай он делает, что им надо. Бросает какое-нибудь исключение, например. Или возвращает некое данное, например то же NaN(). В общем, пусть сами решают, как обработчик писать
                                                  Зачем такой заморочь, когда программист просто может написать обёртку, которая будет вызывать нашу функцию и проверять результат (код корректности), в зависимости от которого делать что надо. Единственное, так будет чуть медленнее, т.к. здесь обёртка будет делать лишний вызов и сравнение, а callback – только в случае. Но это надо ещё одну функцию создавать типа
                                                  ExpandedWrap disabled
                                                    type TFastPowerErrorCallback = function(const Value: Extended; Code, Tag: Integer);
                                                    function FastPowerECB(const X, Y: Extended; ErrorCallback: TFastPowerErrorCallback; Tag: Integer = 0): Extended;
                                                  Если реальный смысл делать это?

                                                  Цитата Qraizer @
                                                  Получилось бы что-то типа:
                                                  К сожалению, C++ знаю плохо, не понимаю фишки :(

                                                  Добавлено
                                                  Вот так:
                                                  ExpandedWrap disabled
                                                    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;
                                                    Цитата Jin X @
                                                    Цитата Славян @
                                                    Имелось ввиду: (-32)-1/5
                                                    Ответ будет 5.66*i, это комплексные числа.
                                                    Эх, а я надеялся всё же увидеть ответ -0,5. :'(
                                                      Цитата Славян @
                                                      Эх, а я надеялся всё же увидеть ответ -0,5.
                                                      Ой, почему-то вычислял (-32)-0.5, а тут (-32)-1/5=0.5i будет.
                                                      А чтобы получилось -0.5, можно сделать так: -(32-1/5)

                                                      Если я всё правильно понимаю...
                                                      Сообщение отредактировано: Jin X -
                                                        Э, нет! Суть именно в том, чтобы из отрицательного взять отрицательную степень и получить нормальный (вещественный) ответ, а не хитрить.

                                                        Добавлено
                                                        Впрочем, можно отмазаться, если -0,2 не представимо точно в FPU (не знаю, не вникал). Но всё равно, подобрать когда всё представимо, думаю, можно попробовать.
                                                          Можно сделать так: sqrt(-5)*sqrt(-5) = -5
                                                            Цитата Jin X @
                                                            Ответ будет 5.66*i, это комплексные числа.

                                                            :blink: откуда комплексные числа?

                                                            ответ будет = 1/(корень 5 степени из -32) = -0,5

                                                            Добавлено
                                                            сорри, уже насчитали)))
                                                              Цитата JoeUser @
                                                              ответ будет = 1/(корень 5 степени из -32) = -0,5
                                                              Ты про что? Ответ какого выражения?
                                                                Цитата Славян @
                                                                если -0,2 не представимо точно в FPU (не знаю, не вникал). Но всё равно, подобрать когда всё представимо, думаю, можно попробовать.
                                                                Наверное не представимо. Там всё - степени двояков, т.е. чётные, так что подобрать честные данные для эксперимента не получится, мыслится мне.
                                                                  Цитата Jin X @
                                                                  Ты про что? Ответ какого выражения?

                                                                  -32 в степени -0.2

                                                                  Добавлено
                                                                  Кстати, JavaScript тоже косячит со своим Math.pow(-32.0,-0.2), возвращает NaN, надо хелпер писать для таких случаев, разбирать четность корня при отрицательной базе

                                                                  Добавлено
                                                                  :lol: А вот Perl - кросава!!!

                                                                  ExpandedWrap disabled
                                                                    print -32.0**-0.2;
                                                                    Действительно - красавцы!

                                                                    Добавлено
                                                                    Эй, а там всё же скобки надо, а? <_<
                                                                      Цитата Славян @
                                                                      Эй, а там всё же скобки надо, а?

                                                                      Неа, там ** - это оператор степени.
                                                                        И что? Он же "-" у 32 опосля степени возьмёт, небось!

                                                                        Добавлено
                                                                        Унарный минус менее важен, нежели степень (в математике), а потому сочтёт как "-(32**-0.2)". Так?
                                                                          У него приоритет ниже чем у отрицания, он выполнится после остальных.
                                                                            Кто "он", у кого "него"? У неё, у степени? Короче, со скобками проверить будет понадёжнее: "(-32)**-0.2".
                                                                              Ну него - оператора степени.
                                                                                Ясно. Странно, но ладно.

                                                                                Добавлено
                                                                                Хм, получается, что на выражение "2**4-2**3" он должен вывалиться с ошибкой, т.к., анализируя "**3", увидел, что берётся степень у "-2", а потом приклеивается результат к другому выражению? Вместо рационального вычисления 24-23. <_<
                                                                                  Нет. Перл это выражение посчитает как 8, т.к. в данном выражении "-" это не унарный минус, а оператор "вычитание".
                                                                                  А вот в таком "2**4**-2**3" это будет унарный минус, и будет последовательное возведение в степень.
                                                                                    PHP на -32**-0.5 выдаёт 0.5, а вот на (-32)**-0.5 выдаёт NAN... А Perl? :)
                                                                                    А вообще, Википедия говорит, что "Корень нечётной степени из отрицательного числа — отрицательное число, однозначно определенное"
                                                                                    Т.е. получается, что действительно (-32)-0.2=-0.5.
                                                                                      Цитата Jin X @
                                                                                      А Perl?
                                                                                      Joe уверяет, что всё норм:
                                                                                      Цитата JoeUser @
                                                                                      А вот Perl - кросава!!!
                                                                                      Там, правда, без скобок -32, но уверяет, что Перл схавает вначале -32, а потом ужо пойдёт степень брать. Я не проверял-с.
                                                                                        Цитата Славян @
                                                                                        Там, правда, без скобок -32
                                                                                        Без скобок и PHP нормально выводит...
                                                                                        0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                                        0 пользователей:


                                                                                        Рейтинг@Mail.ru
                                                                                        [ Script execution time: 0,1041 ]   [ 16 queries used ]   [ Generated: 19.04.24, 23:52 GMT ]