Определение.

Однородная функция степени q — числовая функция f : R^n → R такая, что для любого v ∈ R^n из области определения функции f и любого λ ∈ R выполняется равенство: f(λv)=λ^q f(v), где q — называется порядком однородности.

Для простоты берем q=1, и рассматриваем функции вида f(a,b)=(a^117-b^117)^(1/117), f(a,b,c,d)=(a^117-b^117)^(1/117)-(c^117-d^117)^(1/117).

После несложных численных расчетов на Python и Java были получены следующие равенства.

f(352,54)=351.99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999...
f(357,59)=356.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998972...
f(361,63)=360.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999939...

MS Excel:
f(352,54)=352,000000000001
f(357,59)=357,000000000001
f(361,63)=361,000000000001

Скрипт на Python:

from decimal import *
getcontext().prec = 308
>>> x=(Decimal(352)**Decimal(117)-Decimal(54)**Decimal(117))(Decimal(1)/Decimal(117))
>>> print(x)
351.99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998329159190818894696994980506790444791082984001875203468391468411917936881307214870551679958590777317468915163628481716135549589884152531038661217609555941316588708754835741185821790242245778320061791986803024655
>>> x=(Decimal(357)**Decimal(117)-Decimal(59)**Decimal(117))(Decimal(1)/Decimal(117))
>>> print(x)
356.99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999989720158196073692153897626133606380322329055537315843030235571925317558982699264816534943225755076027658785035832219023824960424396774347405335963769219643742987625523407845824626821939913224289857224063032843297400
>>> x=(Decimal(361)**Decimal(117)-Decimal(63)**Decimal(117))(Decimal(1)/Decimal(117))
>>> print(x)
360.99999999999999999999999999999999999999999999999999999999999999999999999999999999999999993921127936674583510825707397891980952152159386267417777344776761307280088078727565211233452220813716097076319749507809649466951661213836906215116123352999333771519212777104493376322107139264556222426180333043207111704

Скрипт на Java аналогичен, единственно, отличие в том, что надо найти библиотеку
для присвоения вида: RESULT=BigDecimalMath.root(POWER,RESULT);
Советую взять библиотеку A Java Math.BigDecimal Implementation of Core Mathematical Functions

MS Excel:
f(398,100,398,308)=7.38964445190504E-13
f(398,100,398,309)=7.38964445190504E-13

Скрипт на Python:

>>> x=(Decimal(398)**Decimal(117)-Decimal(100)Decimal(117))(Decimal(1)/Decimal(117))-(Decimal(398)**Decimal(117)-Decimal(309)Decimal(117))(Decimal(1)/Decimal(117))
>>> print(x)
4.6829537694880400495961208753068636086170585442527635529935481848840914660367426890426968518388082410943344799080628343292984538641902867227063198133880387010206424683985254813925375685020961046102263610649485204384515121661567412189563550051412170861083133399095734629020724759126523504592133E-13
>>> x=(Decimal(398)**Decimal(117)-Decimal(100)Decimal(117))(Decimal(1)/Decimal(117))-(Decimal(398)**Decimal(117)-Decimal(308)Decimal(117))(Decimal(1)/Decimal(117))
>>> print(x)
3.2048787849158093680423522610101807533554641830481900686328630295592641185012838297491718621152607396025746152496522964996997085198842879841026218584337924367377107257472526086034104095639711035849133200650433251604302283626496677147152423702885746810118429098239541285725629711670483877984277E-13

Вычисления на Java дают аналогичный результат.

При этом на OneNote получаем 0.
(398^117−100^117 )^(1/117)−(398^117−308^117 )^(1/117)=0.0
(398^117−100^117 )^(1/117)−(398^117−309^117 )^(1/117)=0.0

Более того, зададим большую точность каждого члена разности в OneNote.
f(398,100,398,309)=(15357461407072152272595341560605217489962580453253454782381000698280555150698266871781901372815261064006144084350804830440836948323660592372567223353043470694217100899363125243630508686232896955794063869972410449739272809998037351885263675820458842645745358787039602864806831680779682282811435404889161728-1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)^(1/117)-(15357461407072152272595341560605217489962580453253454782381000698280554150698266871781901372815261064006144084350804830440836948323660592372567223353043470694217100899363125243630508686232896955794063869972410449739272809998037351885263675820458842645745358787039602864806831680779682282811435404889161728-2114180645468154536609920593038690001743619316845525182583618652336185889082286837642707603829510005111656415448959134686540978425229790947408474334697737411374763474080732609023460376667948921254970853067562089178774007996892973246633386570133532092567215418841778357322933607577932579981669)^(1/117)=0.0

Что делает его использование непригодным даже для элементарных расчетов.

Однако, рассматривай мы данный пример в Access, то получим:

SELECT (15357461407072152272595341560605217489962580453253454782381000698280555150698266871781901372815261064006144084350804830440836948323660592372567223353043470694217100899363125243630508686232896955794063869972410449739272809998037351885263675820458842645745358787039602864806831680779682282811435404889161728 - 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)^(1/117)-(15357461407072152272595341560605217489962580453253454782381000698280554150698266871781901372815261064006144084350804830440836948323660592372567223353043470694217100899363125243630508686232896955794063869972410449739272809998037351885263675820458842645745358787039602864806831680779682282811435404889161728-2114180645468154536609920593038690001743619316845525182583618652336185889082286837642707603829510005111656415448959134686540978425229790947408474334697737411374763474080732609023460376667948921254970853067562089178774007996892973246633386570133532092567215418841778357322933607577932579981669)^(1/117);

или

SELECT (398^117-100^117)^(1/117)-(398^117-309^117)^(1/117);

с одинаковым результатом f(398,100,398,309)=4,54747350886464E-13.

У MS Word не только своя собственная математика, но и свое понимание вычислений.

Делаем таблицу из одного столбца и вычисляем.

15357461407072152272595341560605217489962580453253454782381000698280555150698266871781901372815261064006144084350804830440836948323660592372567223353043470694217100899363125243630508686232896955794063869972410449739272809998037351885263675820458842645745358787039602864806831680779682282811435404889161728
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
A1-A2 = 2,16
15357461407072152272595341560605217489962580453253454782381000698280554150698266871781901372815261064006144084350804830440836948323660592372567223353043470694217100899363125243630508686232896955794063869972410449739272809998037351885263675820458842645745358787039602864806831680779682282811435404889161728
2114180645468154536609920593038690001743619316845525182583618652336185889082286837642707603829510005111656415448959134686540978425229790947408474334697737411374763474080732609023460376667948921254970853067562089178774007996892973246633386570133532092567215418841778357322933607577932579981669
A5-A4=2,14
A3-A6=0,02

Что совсем неверно (а формула A5-A4=2,14, никак и нигде объяснения не находит) .

Резюме такое. Существует множество пар значений однородных функций от двух и четырех переменных, которые вызывают сложности в MS Office 365 Excel, Word, OneNote, но не в Access.

Комментарии (30)


  1. saboteur_kiev
    31.01.2022 05:06
    +4

    А точно ли дело в каких-то функциях, а не в том, что excel просто не умеет работать с числами такой точности?

    там и двух переменных будет достаточно.


    1. OBIEESupport Автор
      31.01.2022 08:30
      -2

      Технические характеристики и ограничения вычислений

      Точность представления чисел, разрядов, не более

      15

      Допустимое отрицательное число, не менее

      -2,2251E+308

      Допустимое положительное число, не менее

      2,2251E-308

      Допустимое положительное число, не более

      9,99999999999999E+307

      Допустимое отрицательное число, не более

      -9,99999999999999E+307

      Наибольшее положительное число, получаемое в формуле

      1,7976931348623158E+308

      P.S. Разные функции и разные примеры. Я за точность не вышел.


      1. MUTbKA98
        31.01.2022 08:58
        +4

        Точность представления чисел, разрядов, не более

        15

        Сколько разрядов у числа pow(352, 117)?

        Я за точность не вышел


        1. OBIEESupport Автор
          31.01.2022 09:02
          -4

          Извините, точность представления и числом разрядов давайте не путать.

          Но, если очень хочется, то 8820467963926921130312091500044678368409598586829469645973915907304374764958435011512423559373974654245260675316210428277114150357601927000338714393368081033522500474128287533659250261359818063641671088268295219592690846839399955310330080876870476387873784102799185035389119711894256175063888822272


          1. MUTbKA98
            31.01.2022 09:17
            +7

            Давайте не путать.

            Так сколько ж мантисса у (long)double, сколько у этого числа и почему это важно?


            1. OBIEESupport Автор
              31.01.2022 09:31

              8,82046796392692E+297 Мантисса 82046796392692

              4,89857655151656E+202 Мантисса 89857655151656

              Извлекли из разности корень 117 степени

              Получили 3,520000000000010E+02

              Вопрос: как извлекая корень из явно уменьшающегося числа мы получаем число большее?


              1. MUTbKA98
                31.01.2022 09:37
                +4

                А для Вас разница в 95 порядов несущественна?

                Подсказка: Попробуйте не вычитать второе число из первого, а просто извлечь нужный корень из первого числа. Результаты сравнить.


                1. OBIEESupport Автор
                  31.01.2022 09:41
                  -2

                  Да, в моих расчетах разница в 95 порядов существенна. Но вы забываете про 117. Я-то не вычту, а Excel опять показывает 3,520000000000010E+02 ---------------- и вот это называется специально подобранная степень. Попробуйте, пожалуйста.


                  1. Tiriet
                    31.01.2022 10:21
                    +8

                    Ёксель получил два здоровенных числа, отличающихся в 15-16м знаке, и имеющих множитель порядка 10^20. Вычел одно из другого, и получил разницу вида 0,0(15 штук нулей)0352E+20. Нормализовал ее по правилам IEEE754 и получил конечный результат: 3,52(16 нулей)Е+2. Это называется не "правильно подобранная степень", а "незнание матчасти". В смысле, и математической и материальной части.


                    1. OBIEESupport Автор
                      31.01.2022 11:33
                      -2

                      Но он не должен писать корень больше, чем то число из которого я еще и что-то отнял. Почему вы не проверяете тот же Word?


                      1. Tiriet
                        31.01.2022 12:37
                        +2

                        почему нет? Вы взяли число, и возвели его в очень большую степень. Получили совсем большущее число, которое не влезло в разрядность дабла, пришлось обрезать его в 18м значащей цифре, Теперь пытаемся вычислить корень большущей степени из этого числа. но проблема в том, что у этого корня есть погрешность- в последнем бите, и если этот последний бит равен нулю- то приближенное значение отличается от истинного значения сильнее, чем если в этом бите единичка (потому что рассчет большой степени идет тоже с накоплением ошибки). Оки, процессор (не эксель, а процессор!) ставит в этот бит единичку, и опа- оказывается, что приближенное значение оказалось больше.

                        398 и 100 отличаются в 4 раза. 398^117 и 100^117 отличаются в в ~4^117 = 2^234. у них сдвиг на 234 бита. а на весь флоат выделено 64. Поэтому Вы ничего не отнимали от 398^117, Вы сначала вычислили Z=X^117 и чуть-чуть загрубили результат (откинув и округлив примерно 100 значащих младших разрядов, и возможно- увеличив при округлении результат в 16-17 цифре!), получив Z' а потом- вычислили корень, максимально близкий к реальному значению корня из Z'. Вот поэтому у Вас и получилось, что Y~= Z'^(1/117) > X=Z^(1/117).


  1. lamerok
    31.01.2022 06:55
    +2

    После несложных численных расчетов на Python и Java были получены следующие равенства.

    f(352,54)=353.99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999...

    Я может не правильно понял, но как на Python получилось: f(352,54)=353.9. Ведь результат должен быть меньше 352...

    117 степень это далеко за пределами эпсилон для long double, поэтому отнимая, от 352^117 -54^117, вы ровным счетом не делаете ничего, если только ваши тулы не умеют работать с оочень большими числами. Скорее всего эксель этого делать не умеет.


    1. OBIEESupport Автор
      31.01.2022 08:35
      -3

      Я исправил найденную вами опечатку. Я ожидал от Excel прыти Access. Если вам не видно, что он справился с задачей и длиннной арифметикой в рамках double, то прошу посмотреть именно под углом, почему программы MS Office не считают одинаково.

      117 степень это далеко за пределами эпсилон для long double

      Будем опровергать ваше утвержение через C++? Или поверите, что с Access'ом любой результат этой программы совпадет?

      #include <cmath>
      #include <limits>
      #include <iomanip>
      #include <iostream>
      #include <type_traits>
      #include <algorithm>
       
      template<class T>
      typename std::enable_if<!std::numeric_limits<T>::is_integer, bool>::type
          almost_equal(T x, T y, int ulp)
      {
          // the machine epsilon has to be scaled to the magnitude of the values used
          // and multiplied by the desired precision in ULPs (units in the last place)
          return std::fabs(x-y) <= std::numeric_limits<T>::epsilon() * std::fabs(x+y) * ulp
              // unless the result is subnormal
              || std::fabs(x-y) < std::numeric_limits<T>::min();
      }
       
      int main()
      {
          double d1 = 0.2;
          double d2 = 1 / std::sqrt(5) / std::sqrt(5);
          std::cout << std::fixed << std::setprecision(20) 
              << "d1=" << d1 << "\nd2=" << d2 << '\n';
       
          if(d1 == d2)
              std::cout << "d1 == d2\n";
          else
              std::cout << "d1 != d2\n";
       
          if(almost_equal(d1, d2, 2))
              std::cout << "d1 almost equals d2\n";
          else
              std::cout << "d1 does not almost equal d2\n";
      }


      1. lamerok
        31.01.2022 10:05
        +2

        Будем опровергать ваше утвержение через C++?

        как можно опровергнуть истину?

        std::numeric_limits<T>::epsilon() * std::fabs(x)

        Если x = 352^117, epsilon для long double = 1.0842e-19, то для компилятора, все числа в диапазоне что 352^117+- 352^117 * epsilon одинаковые.

        И отнимание 54^117, тут никакой роли уже не играют. Это все будет 352^117.

        А код то вы верный привели, только цифры там не те. Вы те подставьте.


      1. Tiriet
        31.01.2022 10:12
        +6

        почему программы MS Office не считают одинаково

        Потому что студент, окончивший технический ВУЗ и знакомый хотя-бы с азами вычислительной математики знает, что что порядок выполнения операций на числах с плавающей точкой и точность представления самих чисел влияют на конечный результат. Питон умеет в длинные целые числа. Проверьте свои питонячьи формулы на вот таком примере:

        f(352.5,54.5)

        f(357.5,59.5)

        f(361.5,63.5)

        Собственно, вся великолепаная точность Ваших расчетов определяется тем простым фактом, что Вы загнали в свою формулу только целые числа и использовали модуль decimal! Как следствие- расчеты шли в рамках арифметики длинных чисел. Деление целого на длинное целое дало в результате рациональную дробь, которую питон попытался представить максимально точно десятичной дробью, и поэтому в Ваших результатах получилась такая красота. Работали бы с флоатами- все было бы так же, как и в Ёкселе. А корени всей беды в двух вещах- плохое знание математики и незнание документации на модуль Decimal

        decimal — Decimal fixed point and floating point arithmetic

        Source code: Lib/decimal.py

        The decimal module provides support for fast correctly-rounded decimal floating point arithmetic. It offers several advantages over the float datatype:

        • Decimal “is based on a floating-point model which was designed with people in mind, and necessarily has a paramount guiding principle – computers must provide an arithmetic that works in the same way as the arithmetic that people learn at school.” – excerpt from the decimal arithmetic specification.

        • Decimal numbers can be represented exactly. In contrast, numbers like 1.1 and 2.2 do not have exact representations in binary floating point. End users typically would not expect 1.1 + 2.2 to display as 3.3000000000000003 as it does with binary floating point.

        • The exactness carries over into arithmetic. In decimal floating point, 0.1 + 0.1 + 0.1 - 0.3 is exactly equal to zero. In binary floating point, the result is 5.5511151231257827e-017. While near to zero, the differences prevent reliable equality testing and differences can accumulate. For this reason, decimal is preferred in accounting applications which have strict equality invariants.


        1. OBIEESupport Автор
          31.01.2022 10:17
          -4

          Извините, я исследую целые числа.


          1. Tiriet
            31.01.2022 11:58
            +2

            если бы Вы использовали просто целые числа, но ведь Вы используете в питоне-длинные целые числа, а в офисе- простые целые и простые вещественные. У Вас объект исследования в разных условиях разный!


            1. OBIEESupport Автор
              31.01.2022 12:07
              -2

              Вас успокоит, если я напишу, что в OpenOffice я могу пристыковать макрос на Питоне и писать значения прямо в ячейки?

              Или немного проще - выставляя непомемерную длину я как раз и исследую - нужен ли мне код прямого сопряжения Java c MS Office, или мне остаться на внутренних типах данных - а они там double точность имеют. И еще ряд красивых, но далеких от статьи вопросов.


              1. Tiriet
                31.01.2022 12:57
                +2

                не совсем понимаю, что значит "код прямого сопряжения", но с практической точки зрения использовать длинную арфиметику не нужно никому и никогда, точности double достаточно для любых жизненных рассчетов. Обычно достаточно даже single, но в научных рассчетах- уже нет. Да, я знаю про расчеты траекторий спутников схемами Рунге-Кутты 24го порядка точности на вещественных числах повышенной разрядности- но примеры такого рода не относятся к "практической точке зрения". А для практики точность double позволяет описать размер видимой Вселенной с точностью в половину диаметра протона.


                1. OBIEESupport Автор
                  31.01.2022 13:19
                  -1

                  Еще раз пишу, что у меня вполне серьезные расчеты, где double - только первое и очень плохое приближение. совсем понимаю, что значит "код прямого сопряжения", --- это означает что внешняя функция на Java будет видна как внутренняя ф-ция Эксель. расчеты траекторий спутников схемами Рунге-Кутты 24го порядка -- я тоже это видел. И статью поместил, чтобы оценить масштаб проблемы.


                  1. Tiriet
                    31.01.2022 13:44
                    +1

                    Заинтриговали. Можно хоть намекнуть- какая у Вас область науки или техники, что не хватает точности fp64?


      1. mayorovp
        31.01.2022 10:21
        +2

        И что же должен доказать приведённый вами код?


        1. OBIEESupport Автор
          31.01.2022 11:23
          -1

          Код приведен: для Питона - для контроля значений, для Java - мне понравилась сама библиотека.


  1. Neom1an
    31.01.2022 08:56
    +3

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


    1. OBIEESupport Автор
      31.01.2022 08:58
      -4

      Спасибо, первое положительное слово за время существования статьи ). До ПО специфического и его проблем я еще надеюсь дойти.


      1. Tiriet
        31.01.2022 10:16
        +3

        Вы сами использовали специфическое ПО- модуль decimal из python - который работает с длинными числами, со всеми вытекающими из этого плюсами (в виде точных вычислений) и минусами- адско низкая скорсть вычислений, так как все они идут, фактически, "в столбик"- как в школе учили, прямо циферка за циферкой, надо представление числа мегабайт памяти- вот мегабайт и выделится, а не 8 байт на все про все и че хочешь делай.


        1. OBIEESupport Автор
          31.01.2022 13:13
          -2

          Модуль decimal есть в стандарте, кажется, с 2.3 точно. Плюс к этому в 3.3 и 3.6. он модифицировался. И еще, вариантов с такой точностью не так и много. Хоть тушкой, хоть чучелом, но цифры должны считаться. На заре программирования была у меня библиотека на ассемблере из великолепной книжки "Программирование на Паскале для Windows 95". Но лучше все из одной коробки, чем глюки из многих.


          1. Tiriet
            31.01.2022 13:36
            +1

            Времена Windows 95- это "заря программирования"? у меня отец к тому времени уже на третий или четверый язык программирования переходил.

            Но это все никак не отменяет того, что арифметика длинных чисел- это специализированное ПО, заточенное именно под длинные числа, для которых недостаточно ограничений fp64/int64- то есть, их разрядности.


            1. OBIEESupport Автор
              31.01.2022 14:04

              Если считать FoxPro 3 Dos/Win, Dbase2 Dos, Кларион языками программирования, а ассемблер x86, PDP, Фортран II,4,90 за отдельные языки, то это - моя середина. А перфокарточные и ленточные языки я устану перечислять, поэтому я привел книгу, и я - не ваш папа, а, видимо, чуть старше...


    1. Tiriet
      31.01.2022 13:41

      проектирование Шаттлов, кстати, идет на тех же самых fp64, что и бухгалтерия в офисном пакете :-). Я только два раза сталкивался с необходимостью вылезать за их рамки- это упомянутая уже мной астрономическая задача моделирования траекторий спутников с учетом всяких гравитирующих тел- там, емпнип, хватало самописных fp128 и разностных схем очень высокого порядка ( Рунге-Кутты 20 и 24го порядков) и рассчет определителей одних хитрых сильно узко-специальных матриц. А так научные расчеты вполне себе довольствуются реализованной в железе математикой (читай- fp64/int64), и им хватает.