Пришёл мне по работе файл со странной датой. Показывает «17/03/2025», но когда кликаешь на эту ячейку, в строке формул показывает значение «16/03/2025 00:00:00
( Read more... )
Речь идет о формате хранения в памяти вещественных чисел.
То что имеет в виду человек, когда видит запись 0.5-0.4-0.1 это называется формат с фиксированной запятой и там никаких сюрпризов не будет, его также во многих языках называют decimal. (То есть мы храним дробь в виде двух целых чисел само число и степень 10)
В нем удобно вести финансовые операции (почему мне немного странно, что его таблицы не использует по умолчанию)
А то о чем говорит автор и что использует по умолчанию эксель называется формат с плавающей запятой (используется разложение по степеням двойки)
и соответственно появляется мусор, из-за того, что не всегда точно не представляется (периодическая двоичная дробь).
P.S Соответственно когда Эксел считает точно он использует формат с фиксированной запятой и неточно плавающей. У меня в моём варианте электронных таблиц в обоих случаях использовал второй вариант. Чтобы получить ожидаемый интуицией эффект надо выбрать дробный формат
Да ладно, что удобного в decimal для финансовых операций? Он же явно будет жутко медленный. Я в лучшем случае использовал Currency, но это просто целочисленный формат с договорённостью, что мы будем считать последние 4 цифры стоящим после запятой.
Мусор же от округление появляется всегда, какой бы ни была база - собственно, мой пример с 1/3 интуитивен для десятичной, но можно аккуратно показать и реальные примеры для любой системы записи. Кроме символической но это совсем для случаев, когда скорость вычислений не важна.
Всё верно каренси, это как раз частный пример типа с фиксированной запятой и да это по сути целочисленный формат. А теперь собственно почему что-то быстрее или медленнее? Быстрее то, что имеет аппаратную поддержку в случае интов это 64 битные инты, больше уже поддержки не будет, а в случае вещественного числа в плавающем формате это дабл те же 64 бита.
Основная засада в плавающим, что он позволяет делать вычисления с широким диапазоном, но за это мы платим числом значащих цифр в случае дабл это 15 (я думаю, что в Экселе тоже самое).
А в случае децимал 28, 28 это в двух интах по 64 хранят.
Ниже ссылка для понимания, что такое "жутко" медленный (в случае Питона это примерно в 3-4 раз (такие вещи онлайн мерять не очень благодарная затея)). Возможно эксел больше тормозит, это уже от реализации зависит, при правильной реализации, как в Питоне 3.8 допустим, скорость вот такая.
Мне торможения даже вдвое достаточно, чтобы компенсировать ошибку округления! Да даже 10% я не готов заплатить за комфорт иметь больше значащих цифр.
Написал, и понял, что я даже наоборот, в некоторых случаях готов заплатить, чтобы значащих цифр было меньше. В каких случаях мне нужно иметь более 10 значащих цифр? Я же не бухгалтерией занимаюсь, где обязательно нужно свести к нулю какие-то индикаторы. Наоборот, когда я считаю какие-то суммы в десятках миллиардов евро, ни в коем случае не надо делать вид, что у меня правильно посчитаны сантимы. У нас точность модели (Монте-Карло, считаем чисто как разброс результата в зависимости от выбора другого random number seed) - несколько миллионов. Ну и зачем мне хранить тысячные доли?
В моём случае с датой проблема же как раз в том, что тип данных был слишком точным. Если бы округление было на уровне секунды, или хотя бы тысячной доли секунды, всё было бы отлично. А бага вылезла именно потому, что Excel "почему-то" (понятно даже, почему) решил хранить слишком много цифр.
есть хороший бесплатный французский калькулятор для математиков, называется gp/pari я его себе везде установил и считаю только на нем. он очень умный и у него неограниченная точность.
например, если ввести число как дробь 1/17, то он именно так и будет его хранить и обрабатывать, как 1/17, без перевода в другие представления и без округлений. я просто обожаю его, очень правильный и умный калькулятор. конечно на фоне этого и другого подобного (matlab, mathematica, etc) микрософт это просто каменный век
Это не каменный век, это просто про другое. Как сравнивать молоток и комбайн - комбайном крайне неудобно забивать гвозди, все в курсе.
Если мне нужно посчитать что-то одно, наверняка есть какие-то более удобные, чем Excel утилиты. Но лично я, в данном случае, использую Excel как средство передачи большого объёма данных от человека к человеку. Опять же, были бы на двух концах этой передачи роботы, наверняка можно было бы придумать и что-то другое. Но тут нужна не только возможность передать "одним файлом" миллионы чисел, но и возможность легко открыть, посмотреть и исправить какие-то данные человеком. Это не "калькулятор", это другое использование.
Ну и в качестве калькулятора тоже Excel во многом не имеет себе равных. Понятно, что символическая математика красивая, и проблем с округлением у неё не возникает гораздо дольше, чем у математики с плавающей точкой. Но если у меня файл с десятками тысяч линий, и в каждой несколько десятков формул, то мне нужно, чтобы всё это считалось быстро, крайне быстро. На одном расчёте я могу "подождать
( ... )
понятно. для передачи данных я использую текстовые файлы. ну там csv или просто plain text. а чем их потом читать и как обрабатывать это всегда отдельно. т.е. мухи отдельно от котлет ;-))
Так а в чём разница? Эти текстовые файлы тоже ведь не из вакуума берутся. Ну запишу я "45732.999999999993" в .cvs (у меня в примере он был в .xml) - что это изменит? Нет, тут же вопрос принципиальный: если мы работаем с плавающей запятой, где-то придётся задуматься о правилах и "ошибках" округления.
У меня в каком-то конкретном компиляторе плюсов была формула типа (2+0.4)+0.2 - для прозрачности кода хотелось использовать именно выражение с константами. Результат первого сложения преобразовался в целочисленный тип - но на этапе оптимизации, до трансляции. То есть в код выражение уже пошло как константная 2.
Ой, да, я когда-то изучал вариант перейти на целочисленные переменные в MatLab, но попытался сначала разобраться с вот такими вот неявными преобразованиями, потом попытался вообразить всевозможные ошибки, которые вылезут - и не стал рекомендовать переход. Double, конечно, дорогой и неточный, но зато универсальный.
Я рекомендую явно типизировать константы (хотя бы писать не 2, а 2.0), потому что все это все равно соптимизируется на этапе компиляции и на быстродействие не повлияет. Это такая же полезная привычка как использовать скобки когда приоритет выполнения операций может повлиять на результат (это не такой редкий случай, как принято считать, даже без казусов неявной типизации) или вообще вызвать сомнения. Скобки же тоже уйдут при компиляции.
Но тут конечно есть разница, потому что табличные процессоры по сути интерпретаторы и никто точно не знает, будет ли оно типизировать на каждой итерации, особенно в следующей версии этого же пакета.
Comments 24
Reply
Речь идет о формате хранения в памяти вещественных чисел.
То что имеет в виду человек, когда видит запись 0.5-0.4-0.1 это называется формат с фиксированной запятой и там никаких сюрпризов не будет, его также во многих языках называют decimal. (То есть мы храним дробь в виде двух целых чисел само число и степень 10)
В нем удобно вести финансовые операции (почему мне немного странно, что его таблицы не использует по умолчанию)
А то о чем говорит автор и что использует по умолчанию эксель называется формат с плавающей запятой (используется разложение по степеням двойки)
и соответственно появляется мусор, из-за того, что не всегда точно не представляется (периодическая двоичная дробь).
https://www.online-python.com/qpKOfg06cT
P.S Соответственно когда Эксел считает точно он использует формат с фиксированной запятой и неточно плавающей. У меня в моём варианте электронных таблиц в обоих случаях использовал второй вариант. Чтобы получить ожидаемый интуицией эффект надо выбрать дробный формат
Reply
Мусор же от округление появляется всегда, какой бы ни была база - собственно, мой пример с 1/3 интуитивен для десятичной, но можно аккуратно показать и реальные примеры для любой системы записи. Кроме символической но это совсем для случаев, когда скорость вычислений не важна.
Reply
Всё верно каренси, это как раз частный пример типа с фиксированной запятой и да это по сути целочисленный формат. А теперь собственно почему что-то быстрее или медленнее? Быстрее то, что имеет аппаратную поддержку в случае интов это 64 битные инты, больше уже поддержки не будет, а в случае вещественного числа в плавающем формате это дабл те же 64 бита.
Основная засада в плавающим, что он позволяет делать вычисления с широким диапазоном, но за это мы платим числом значащих цифр в случае дабл это 15 (я думаю, что в Экселе тоже самое).
А в случае децимал 28, 28 это в двух интах по 64 хранят.
Ниже ссылка для понимания, что такое "жутко" медленный (в случае Питона это примерно в 3-4 раз (такие вещи онлайн мерять не очень благодарная затея)). Возможно эксел больше тормозит, это уже от реализации зависит, при правильной реализации, как в Питоне 3.8 допустим, скорость вот такая.
https://www.online-python.com/gnBtLzRC4f
Reply
Мне торможения даже вдвое достаточно, чтобы компенсировать ошибку округления! Да даже 10% я не готов заплатить за комфорт иметь больше значащих цифр.
Написал, и понял, что я даже наоборот, в некоторых случаях готов заплатить, чтобы значащих цифр было меньше. В каких случаях мне нужно иметь более 10 значащих цифр? Я же не бухгалтерией занимаюсь, где обязательно нужно свести к нулю какие-то индикаторы. Наоборот, когда я считаю какие-то суммы в десятках миллиардов евро, ни в коем случае не надо делать вид, что у меня правильно посчитаны сантимы. У нас точность модели (Монте-Карло, считаем чисто как разброс результата в зависимости от выбора другого random number seed) - несколько миллионов. Ну и зачем мне хранить тысячные доли?
В моём случае с датой проблема же как раз в том, что тип данных был слишком точным. Если бы округление было на уровне секунды, или хотя бы тысячной доли секунды, всё было бы отлично. А бага вылезла именно потому, что Excel "почему-то" (понятно даже, почему) решил хранить слишком много цифр.
Reply
называется gp/pari я его себе везде установил и считаю только на нем.
он очень умный и у него неограниченная точность.
например, если ввести число как дробь 1/17, то он именно так и будет
его хранить и обрабатывать, как 1/17, без перевода в другие представления
и без округлений. я просто обожаю его, очень правильный и умный калькулятор.
конечно на фоне этого и другого подобного (matlab, mathematica, etc) микрософт
это просто каменный век
https://pari.math.u-bordeaux.fr/
если лень устанавливать он там у них и прямо в браусре работает:
? 1/17+1/132
%1 = 149/2244
Reply
Это не каменный век, это просто про другое. Как сравнивать молоток и комбайн - комбайном крайне неудобно забивать гвозди, все в курсе.
Если мне нужно посчитать что-то одно, наверняка есть какие-то более удобные, чем Excel утилиты. Но лично я, в данном случае, использую Excel как средство передачи большого объёма данных от человека к человеку. Опять же, были бы на двух концах этой передачи роботы, наверняка можно было бы придумать и что-то другое. Но тут нужна не только возможность передать "одним файлом" миллионы чисел, но и возможность легко открыть, посмотреть и исправить какие-то данные человеком. Это не "калькулятор", это другое использование.
Ну и в качестве калькулятора тоже Excel во многом не имеет себе равных. Понятно, что символическая математика красивая, и проблем с округлением у неё не возникает гораздо дольше, чем у математики с плавающей точкой. Но если у меня файл с десятками тысяч линий, и в каждой несколько десятков формул, то мне нужно, чтобы всё это считалось быстро, крайне быстро. На одном расчёте я могу "подождать ( ... )
Reply
Reply
Так а в чём разница? Эти текстовые файлы тоже ведь не из вакуума берутся. Ну запишу я "45732.999999999993" в .cvs (у меня в примере он был в .xml) - что это изменит? Нет, тут же вопрос принципиальный: если мы работаем с плавающей запятой, где-то придётся задуматься о правилах и "ошибках" округления.
Reply
Reply
Ой, да, я когда-то изучал вариант перейти на целочисленные переменные в MatLab, но попытался сначала разобраться с вот такими вот неявными преобразованиями, потом попытался вообразить всевозможные ошибки, которые вылезут - и не стал рекомендовать переход. Double, конечно, дорогой и неточный, но зато универсальный.
Reply
Но тут конечно есть разница, потому что табличные процессоры по сути интерпретаторы и никто точно не знает, будет ли оно типизировать на каждой итерации, особенно в следующей версии этого же пакета.
Reply
И как дальше жить?
Reply
Прекрасно дальше жить :-)
Reply
Leave a comment