Типы чисел в DSL
От: Alekzander  
Дата: 01.12.23 21:18
Оценка:
Возник вопрос на стыке проектирования, UX и БД )) Требуются ваши мнения.

Мне нужно спроектировать DSL. С одной стороны, он должен быть строго типизирован (это требование), а с другой — этот тип появится на уровне GUI для массовых пользователей. А их, по возможности, хотелось бы не грузить разницей между int и double (не говоря про потерю точности), а дать им вместо этого некий универсальный тип number. С другой стороны, возможно, стоит один раз научить юзеров разнице между int и double, чем разруливать миллион неоднозначностей.

Что еще хуже, иногда возможно хранение в переменных сумм денег. Как я знаю, в таких случаях принято использовать третий тип: с эмуляцией вещественности через целые (нужны гарантии, что 0.1 + 0.2 == 0.3). Но три разных типа для чисел — для юзеров это уже будет перебор. Или нет? Может, как раз дать им кучу типов и пусть сами несут ответственность за сходимость балансов? ))

Сами значения будут храниться в sqlite (он лёгкий, встраиваемый и опенсорсный, но если есть альтернативы, можно рассмотреть). Доступ к ним планируется только через слой этого DSL'я, хотя, конечно же, желательно сохранить возможность обработки (в т.ч. вычислений) через запросы. Я так понимаю, придётся все агрегирующие функции писать самому?

Итак, что посоветуете для внутреннего представления чисел в памяти и хранения в sqlite? И какими типами это всё оформить для юзеров?
Re: Типы чисел в DSL
От: IT Россия linq2db.com
Дата: 01.12.23 23:58
Оценка: 3 (1)
Здравствуйте, Alekzander, Вы писали:

A>Итак, что посоветуете для внутреннего представления чисел в памяти и хранения в sqlite? И какими типами это всё оформить для юзеров?


На вскидку я бы ещё тип percent рассмотрел. А вообще, с бы этот вопрос задал тем, кто шарит в 1C. Всё же там накоплен ахренительно немалый опыт по данной теме.

По поводу sqlite, то желательно подробности. Если предполагается минимум данных и нежелательность возни с установками дополнительного софта, то sqlite нормальный выбор.
Если нам не помогут, то мы тоже никого не пощадим.
Re: Типы чисел в DSL
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.12.23 00:58
Оценка: 3 (1)
Здравствуйте, Alekzander, Вы писали:

A>Мне нужно спроектировать DSL. С одной стороны, он должен быть строго типизирован (это требование), а с другой — этот тип появится на уровне GUI для массовых пользователей. А их, по возможности, хотелось бы не грузить разницей между int и double (не говоря про потерю точности), а дать им вместо этого некий универсальный тип number. С другой стороны, возможно, стоит один раз научить юзеров разнице между int и double, чем разруливать миллион неоднозначностей.


https://github.com/al-martyn1/marty_decimal


A>Что еще хуже, иногда возможно хранение в переменных сумм денег. Как я знаю, в таких случаях принято использовать третий тип: с эмуляцией вещественности через целые (нужны гарантии, что 0.1 + 0.2 == 0.3). Но три разных типа для чисел — для юзеров это уже будет перебор. Или нет? Может, как раз дать им кучу типов и пусть сами несут ответственность за сходимость балансов? ))


https://github.com/al-martyn1/marty_decimal


A>Сами значения будут храниться в sqlite (он лёгкий, встраиваемый и опенсорсный, но если есть альтернативы, можно рассмотреть). Доступ к ним планируется только через слой этого DSL'я, хотя, конечно же, желательно сохранить возможность обработки (в т.ч. вычислений) через запросы. Я так понимаю, придётся все агрегирующие функции писать самому?


https://github.com/al-martyn1/marty_decimal


A>Итак, что посоветуете для внутреннего представления чисел в памяти и хранения в sqlite? И какими типами это всё оформить для юзеров?


https://github.com/al-martyn1/marty_decimal

Маньяк Робокряк колесит по городу
Re: Типы чисел в DSL
От: vsb Казахстан  
Дата: 02.12.23 01:13
Оценка: 3 (1) -1
Посоветую взять JavaScript и всё. Число это просто double (64-битная плавающая точка).
Отредактировано 02.12.2023 1:13 vsb . Предыдущая версия .
Re[2]: Типы чисел в DSL
От: Alekzander  
Дата: 02.12.23 09:51
Оценка: 40 (1)
Здравствуйте, vsb, Вы писали:

vsb>Посоветую взять JavaScript и всё. Число это просто double (64-битная плавающая точка).


Re: Типы чисел в DSL
От: Pzz Россия https://github.com/alexpevzner
Дата: 02.12.23 10:48
Оценка: 3 (1) +1
Здравствуйте, Alekzander, Вы писали:

A>Мне нужно спроектировать DSL. С одной стороны, он должен быть строго типизирован (это требование), а с другой — этот тип появится на уровне GUI для массовых пользователей. А их, по возможности, хотелось бы не грузить разницей между int и double (не говоря про потерю точности), а дать им вместо этого некий универсальный тип number. С другой стороны, возможно, стоит один раз научить юзеров разнице между int и double, чем разруливать миллион неоднозначностей.


Можно сделать некий универсальный тип int и некий универсальный тип float. Но объединить не получится, у них слишком разные свойства. И эта разница в свойствах, она существенна при выборе типа.

От этого можно отступить, только если все эти тонкости пользователям не важны. Как в JavaScript, например; там все числа — это 64-битный floating point, но известно, что в довольно широком диапазоне целые в нем представляются без потерь точности, поэтому их можно использовать в качестве счетчиков циклов и т.п., особо не задумываясь.

А вот важны эти тонкости пользователям или нет — зависит от самих пользователей и от решаемых ими задач. И это надо как-то с ними обсудить.

A>Что еще хуже, иногда возможно хранение в переменных сумм денег. Как я знаю, в таких случаях принято использовать третий тип: с эмуляцией вещественности через целые (нужны гарантии, что 0.1 + 0.2 == 0.3). Но три разных типа для чисел — для юзеров это уже будет перебор. Или нет? Может, как раз дать им кучу типов и пусть сами несут ответственность за сходимость балансов? ))


Fixed point. Это когда счет идет, например, в сотых. Или в тысячных. Но конкретный выбор фиксируется на уровне типа и не меняется в процессе рассчетов, в отличии от float. Можно объединить с целыми, они — частный случай фиксированной точки.

A>Итак, что посоветуете для внутреннего представления чисел в памяти и хранения в sqlite? И какими типами это всё оформить для юзеров?


Я бы шел от пользовательского интерфейса (который, в данном случае — твоя система типов, видимая пользователям). А когда там устаканится, уже думал бы о деталях реализации.
Re[2]: Типы чисел в DSL
От: Alekzander  
Дата: 02.12.23 11:01
Оценка:
Здравствуйте, IT, Вы писали:

IT>На вскидку я бы ещё тип percent рассмотрел.


Спасибо за напоминание, это хорошая идея. Но я думаю, это сугубо вторичная вещь, которую как тип оформлять вообще не надо. На уровне GUI можно сделать галку "Это проценты". А на уровне DSL... лет двадцать назад мой друг писал эвалюатор математических выражений. Он сделал очень просто: заменял знак % на "/100.0" где это было синтаксически уместно. Можно было написать pi*50% и получить 1.57... Как выяснилось за двадцать лет использования, этот трюк покрывает все юзерские хотелки.

IT>По поводу sqlite, то желательно подробности. Если предполагается минимум данных и нежелательность возни с установками дополнительного софта, то sqlite нормальный выбор.


Так а какие подробности? Все данные имеют характер табличных и хранятся в таблицах. Впрочем, вот две важных подробности. Первая. Нужно, чтобы это собиралось, работало и не тормозило на недорогом телефоне с Android. Тут, я думаю, проблем не будет — в одной компании, где я работал 10 лет назад, sqlite использовали ещё под WinMo на ARM'ах тех времён. Вторая. Нужно много вычислений по формулам (как для каждой строки в вычисляемых колонках, так и для таблицы в целом — min/max/avg/etc). Хранить ли вычисленное и перевычислять из триггеров, или вычислять всё каждый раз на лету — я ещё не решил, мне, так или иначе, понадобится написать eval(), а во втором случае желательно иметь удобный способ его вызова, инициируемый из запроса.
Re[2]: Типы чисел в DSL
От: Alekzander  
Дата: 02.12.23 11:08
Оценка:
Здравствуйте, Marty, Вы писали:

M>https://github.com/al-martyn1/marty_decimal

M>https://github.com/al-martyn1/marty_decimal
M>https://github.com/al-martyn1/marty_decimal
M>https://github.com/al-martyn1/marty_decimal

Я правильно понимаю, что ты посоветовал использовать number, и предложил имплементацию? Если да, можно о ней хотя бы в двух словах рассказать, в частности о том, как сериализовать значения (записывать в sqlite)?
Re[3]: Типы чисел в DSL
От: vsb Казахстан  
Дата: 02.12.23 11:12
Оценка:
Здравствуйте, Alekzander, Вы писали:

vsb>>Посоветую взять JavaScript и всё. Число это просто double (64-битная плавающая точка).


A>Image: firefox_K8XYZyZaEJ.png


Требование про 0.3 не несёт смысла, поэтому я его даже не рассматриваю. Если хочешь обсудить — расскажи подробней, зачем тебе такое требование и какую задачу ты хочешь с его помощью решать. Пока у тебя нет деления, проще всего просто представлять все числа в копейках (или сотых долях копейки, или тебе видней, какая у тебя гранулярность планируется), в double 64 можно засунуть 52-битовое целое число, такого размера хватит для всех разумных целей. Если есть деление — проще с округлением аккуратно работать. Опять же точности double хватит для подавляющего большинства случаев на практике.
Отредактировано 02.12.2023 11:16 vsb . Предыдущая версия . Еще …
Отредактировано 02.12.2023 11:15 vsb . Предыдущая версия .
Re[3]: Типы чисел в DSL
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.12.23 12:09
Оценка:
Здравствуйте, Alekzander, Вы писали:

A>Я правильно понимаю, что ты посоветовал использовать number, и предложил имплементацию?


Типа того


A>Если да, можно о ней хотя бы в двух словах рассказать, в частности о том, как сериализовать значения (записывать в sqlite)?


Есть метод std::string toString(int precision) const


Более того, я этот тип писал, чтобы а) хранить деньги без всяких округлений, любые суммы, б) хранить это в базе sqlite
Маньяк Робокряк колесит по городу
Отредактировано 02.12.2023 12:13 Marty . Предыдущая версия .
Re[3]: Типы чисел в DSL
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.12.23 12:12
Оценка:
Здравствуйте, Alekzander, Вы писали:

A>Так а какие подробности? Все данные имеют характер табличных и хранятся в таблицах. Впрочем, вот две важных подробности. Первая. Нужно, чтобы это собиралось, работало и не тормозило на недорогом телефоне с Android.


sqlite в андроиде примерно в каждой аппе прикручен. Например, whatsapp хранит базу сообщений в нём
Маньяк Робокряк колесит по городу
Re[4]: Типы чисел в DSL
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.12.23 12:18
Оценка: +3
Здравствуйте, vsb, Вы писали:

A>>Image: firefox_K8XYZyZaEJ.png


vsb>Требование про 0.3 не несёт смысла, поэтому я его даже не рассматриваю. Если хочешь обсудить — расскажи подробней, зачем тебе такое требование и какую задачу ты хочешь с его помощью решать. Пока у тебя нет деления, проще всего просто представлять все числа в копейках (или сотых долях копейки, или тебе видней, какая у тебя гранулярность планируется),


А потом захочется другую валюту, с другим количеством условных копеек в условном рубле, и вся эта схема накроется пимедным тзом.


vsb>в double 64 можно засунуть 52-битовое целое число, такого размера хватит для всех разумных целей. Если есть деление — проще с округлением аккуратно работать. Опять же точности double хватит для подавляющего большинства случаев на практике.


В double денег влезает, на самом деле не очень много. Хотя, для домашней бухгалтерии, может и хватит.

Но вообще, хранить деньги в double — очень, очень плохая идея.
Маньяк Робокряк колесит по городу
Re[5]: Типы чисел в DSL
От: vsb Казахстан  
Дата: 02.12.23 13:52
Оценка:
Здравствуйте, Marty, Вы писали:

M>В double денег влезает, на самом деле не очень много. Хотя, для домашней бухгалтерии, может и хватит.


45 триллионов рублей, если считать с копейками. Неплохая у вас домашняя бухгалтерия.
Re[6]: Типы чисел в DSL
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.12.23 14:25
Оценка:
Здравствуйте, vsb, Вы писали:

M>>В double денег влезает, на самом деле не очень много. Хотя, для домашней бухгалтерии, может и хватит.


vsb>45 триллионов рублей, если считать с копейками. Неплохая у вас домашняя бухгалтерия.


Попиливал бухгалтерию для торговли на бирже. Прикинул, что вполне могут произойти ситуации, какие-нибудь агрегированные расчеты за года, когда не влезу
Маньяк Робокряк колесит по городу
Re[6]: Типы чисел в DSL
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.12.23 14:32
Оценка:
Здравствуйте, vsb, Вы писали:

M>>В double денег влезает, на самом деле не очень много. Хотя, для домашней бухгалтерии, может и хватит.


vsb>45 триллионов рублей, если считать с копейками. Неплохая у вас домашняя бухгалтерия.


Кстати, некоторые акции торгуются по ценам с шестью знаками после точки (в рублях). 640двух знаков под копейки хватит всем, ага
Маньяк Робокряк колесит по городу
Re[7]: Типы чисел в DSL
От: vsb Казахстан  
Дата: 02.12.23 14:33
Оценка:
Здравствуйте, Marty, Вы писали:

M>>>В double денег влезает, на самом деле не очень много. Хотя, для домашней бухгалтерии, может и хватит.


vsb>>45 триллионов рублей, если считать с копейками. Неплохая у вас домашняя бухгалтерия.


M>Попиливал бухгалтерию для торговли на бирже. Прикинул, что вполне могут произойти ситуации, какие-нибудь агрегированные расчеты за года, когда не влезу


Очень сомневаюсь, что потеря нижних битов в таких отчётах на что-то повлияет. Типа мы за 33 года имели оборот не 50 123 456 789 111 а 50 123 456 789 121 рублей. Обычно такие числа даже на выводе обрезают, чтобы читать можно было.

Ну и в конце концов для такой специализированной задачи можно и BigInt взять конкретно в этом отчёте.
Re[8]: Типы чисел в DSL
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.12.23 14:37
Оценка: +1
Здравствуйте, vsb, Вы писали:

M>>Попиливал бухгалтерию для торговли на бирже. Прикинул, что вполне могут произойти ситуации, какие-нибудь агрегированные расчеты за года, когда не влезу


vsb>Очень сомневаюсь, что потеря нижних битов в таких отчётах на что-то повлияет. Типа мы за 33 года имели оборот не 50 123 456 789 111 а 50 123 456 789 121 рублей. Обычно такие числа даже на выводе обрезают, чтобы читать можно было.


А я сомневаюсь, что это можно просто проигнорировать


vsb>Ну и в конце концов для такой специализированной задачи можно и BigInt взять конкретно в этом отчёте.


Зачем в разных отчетах использовать разные типы? Если вкорячивать BigInt/BigNumber, почему сразу их везде не использовать и не беспокоится, что где-то что-то в какой-то момент пропадёт?
Маньяк Робокряк колесит по городу
Re[9]: Типы чисел в DSL
От: vsb Казахстан  
Дата: 02.12.23 15:20
Оценка:
Здравствуйте, Marty, Вы писали:

M>Зачем в разных отчетах использовать разные типы? Если вкорячивать BigInt/BigNumber, почему сразу их везде не использовать и не беспокоится, что где-то что-то в какой-то момент пропадёт?


Потому, что double работает очень быстро, а bigint работает очень медленно. Потому, что double поддерживается практически всем софтом, а bigint — далеко не всем, в частности пресловутым sqlite не поддерживается. Делать софт медленней на порядок-два ради мнимых юзкейсов я считаю неправильным.
Re[10]: Типы чисел в DSL
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.12.23 15:59
Оценка: +1
Здравствуйте, vsb, Вы писали:

vsb>Потому, что double работает очень быстро, а bigint работает очень медленно.


Очень медленно — это насколько медленно?

У меня очень медленно только деление работает, остальные операции медленно, но уже не очень. +/- работают в 20 раз медленее, умножение — в 50 раз. Это медленно, конечно, но не прям уж так. Если мы не САПР/3D пишем, этим можно пренебречь.

И, в принципе, это ещё можно раза в два ускорить — у меня по байту на десятичный знак, а можно упаковать два знака в байт, это будет побыстрее, но мне лень было, писать несколько посложнее бы было


vsb>Потому, что double поддерживается практически всем софтом, а bigint — далеко не всем,


Что значит — поддерживается?


vsb>в частности пресловутым sqlite не поддерживается.


В частности в пресловутом sqlite внезапно всё хранится строками, а вот всякие обёртки, уже да, любят в дабл конвертить


vsb>Делать софт медленней на порядок-два ради мнимых юзкейсов я считаю неправильным.



Софт не будет медленнее на порядки, потому что операции с этими числами там будут занимать доли процентов от общего времени работы. Никто этого не заметит. А вот гарантии того, что в числе ни один знак не пропадёт и не изменится — в некоторых случаях дорогого стоят. У BigDecimal есть ещё приятная особенность, что можно числа прямо сравнивать, и не приседать с точностью представления.

И ещё по поводу скорости. У меня есть интерфейс рисования, обёртка над GDI и GDI+, и вот там я сделал так, что можно везде использовать double, а можно мой Decimal. Так вот, отрисовка сцены не отличается ни на милисекунды при использовании того или другого, всё равно всё время сжирают вызовы GDI, нужно очень огромные сцены рисовать, с сотнями/тысячами объектов, чтобы тип чисел начал как-то влиять.


А вообще, тех, кто считает деньги в double — их надо сразу расстреливать
Маньяк Робокряк колесит по городу
Re[11]: Типы чисел в DSL
От: vsb Казахстан  
Дата: 02.12.23 16:33
Оценка:
Здравствуйте, Marty, Вы писали:

M>Софт не будет медленнее на порядки, потому что операции с этими числами там будут занимать доли процентов от общего времени работы. Никто этого не заметит. А вот гарантии того, что в числе ни один знак не пропадёт и не изменится — в некоторых случаях дорогого стоят.


Ключевое выделил. Твой пример с биржой и 6 знаками после запятой, вероятно, относится к этим некоторым случаям. 99% остальных юз-кейсов, вероятно, не относятся к этим случаям.

M>У BigDecimal есть ещё приятная особенность, что можно числа прямо сравнивать, и не приседать с точностью представления.


Это пока у тебя деления нет в алгоритмах. Когда появится — там и до рациональных чисел дойти, возможно, придётся. А то и до символьных вычислений.

M>А вообще, тех, кто считает деньги в double — их надо сразу расстреливать


Не убедительно.
Re[12]: Типы чисел в DSL
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.12.23 16:46
Оценка:
Здравствуйте, vsb, Вы писали:

M>>Софт не будет медленнее на порядки, потому что операции с этими числами там будут занимать доли процентов от общего времени работы. Никто этого не заметит. А вот гарантии того, что в числе ни один знак не пропадёт и не изменится — в некоторых случаях дорогого стоят.


vsb>Ключевое выделил. Твой пример с биржой и 6 знаками после запятой, вероятно, относится к этим некоторым случаям. 99% остальных юз-кейсов, вероятно, не относятся к этим случаям.


Мой пример относится к любому финансовому софту. Ну, кроме такого, который написать, запустить, и навсегда забыть. Иначе через 5-10-20 лет это вылезет в виде какой-то внезапной жопы, и что-то сделать уже будет малореально. Это ещё если ты из-за каких-нибудь незамеченных округлений не влетишь на штрафы от фискальных органов


M>>У BigDecimal есть ещё приятная особенность, что можно числа прямо сравнивать, и не приседать с точностью представления.


vsb>Это пока у тебя деления нет в алгоритмах. Когда появится — там и до рациональных чисел дойти, возможно, придётся. А то и до символьных вычислений.


А в финансах вообще мало делят, там всё больше прибавляют и приумножают Но и в 2D графике у меня мало делений, да и в 3D вроде их не намного больше. И часто, на самом деле, от лишних делений можно просто избавиться, просто оптимизировав алгоритм. Даже если надо на каждом шаге что-то делать, часто такое можно заменить на умножение на обратную величину, которая считается реже. Или просто достаточно один раз в конце разделить, а не на каждом шаге. Но вообще, я пока с проблемами перфоманса по вине своих Decimal не сталкивался, хотя я их много где вместо даблов стал использовать


M>>А вообще, тех, кто считает деньги в double — их надо сразу расстреливать


vsb>Не убедительно.


Если будешь писать финансовый софт — скажи нам название, чтобы мы его стороной обходили
Маньяк Робокряк колесит по городу
Re[4]: Типы чисел в DSL
От: Alekzander  
Дата: 02.12.23 21:51
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Требование про 0.3 не несёт смысла, поэтому я его даже не рассматриваю. Если хочешь обсудить — расскажи подробней, зачем тебе такое требование и какую задачу ты хочешь с его помощью решать.


Если ты пишешь калькулятор, ты не знаешь, что с его помощью будут считать юзеры. Твоё дело выдавать результат без сюрпризов. У меня не калькулятор, но суть-то та же.

Вариант просто взять самый большой float из sqlit'овских, назвать его number и отказаться от гарантий точности (т.е. сделать как в JS) — нормальный рабочий вариант, просто хотелось бы сначала понять, что лучше ничего не придумаешь. Вопрос, собственно, и был об этом.
Отредактировано 02.12.2023 22:22 Alekzander . Предыдущая версия .
Re[5]: Типы чисел в DSL
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.12.23 22:11
Оценка: +1
Здравствуйте, Alekzander, Вы писали:

A>Вариант просто взять самый большой float из sqlit'овских и назвать его number (т.е. сделать как в JS) — нормальный рабочий вариант, просто хотелось бы сначала понять, что лучше ничего не придумаешь. Вопрос, собственно, и был об этом.


Если именно формат с плавающей точкой — ну, можно и его взять, больше дабла всё равно ничего не будет. Но в SQL есть NUMBER — там и размер, и точность задаётся. Всё финансовое хранится только так.

Для начала надо бы понять, какими проблемами вылезет потом внезапная потеря значащих цифр. Для вещественных чисел в технических вузах дают курс "вычислительная математика"/"численные методы" на семестр-два, в котором разбирают все основные грабли работы с этими числами при численном решении математических задач. Но там потеря значащих цифр допустима. Для бабла ничего лучше BigNumbers нет
Маньяк Робокряк колесит по городу
Re[2]: Типы чисел в DSL
От: Alekzander  
Дата: 02.12.23 22:12
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Я бы шел от пользовательского интерфейса (который, в данном случае — твоя система типов, видимая пользователям). А когда там устаканится, уже думал бы о деталях реализации.


Идеальный GUI — это когда ты выбираешь тип number, а потом вводишь любые дробные и целые числа в пределах диапазона, и они складываются без потери точности. Но ты же сам пишешь, что "не получится". Тогда какой смысл со стороны GUI смотреть, не думая о реализуемости? Мне нужно оптимальное решение, т.е. наилучший GUI, но не вообще, а из тех, что технически реализуемы и не приведут к граблям.

Pzz>А вот важны эти тонкости пользователям или нет — зависит от самих пользователей и от решаемых ими задач. И это надо как-то с ними обсудить.


Когда ты пишешь тул типа калькулятора, глупо обсуждать с юзерами, что они будут на нём считать, а что нет. Я просто предвижу, что рано или поздно кто-нибудь напишет ==, и это приведёт к проблемам. Кстати, может просто реализовать == через эпсилон, а вывод загрублять на один-два разряда по сравнению с родной точностью double'а того размера, который поддерживается в sqlite'е? Такое будет работать?

Pzz>Fixed point. Это когда счет идет, например, в сотых. Или в тысячных. Но конкретный выбор фиксируется на уровне типа и не меняется в процессе рассчетов, в отличии от float. Можно объединить с целыми, они — частный случай фиксированной точки.


Я понимаю, что fixed point. Что с ним делать-то? Отдельным типом юзерам дать? Financial number? Или уж сразу объединить с видом валюты, сделать точность два знака после точки, и назвать этот тип currency? Будет number (т.е. double) и currency (т.е. int * 100 + enum валюты).

А нельзя сделать вообще всё (универсальный number) на базе fixed point?

Если что, меня устроит ссылка на какой-нибудь фундаментальный труд "Типы чисел и их представления", если это где-то разжёвано, пойду просвещаться.
Отредактировано 02.12.2023 22:19 Alekzander . Предыдущая версия .
Re: Типы чисел в DSL
От: hi_octane Беларусь  
Дата: 03.12.23 01:51
Оценка: 3 (1) +1
A>Итак, что посоветуете для внутреннего представления чисел в памяти и хранения в sqlite? И какими типами это всё оформить для юзеров?

Если твой DSL заточен на простоту и скорость не принципиальна — я бы создал один тип Number на все применения, на обыкновенных дробях. Как BigRational в Java и C#. Наверняка и для других языков готовые либы есть.

Плюсы — любая точность без округлений, любое число знаков после запятой, возможность хранить на любой платформе одинаковой строкой, не зависящей от железа. Сохранится без потерь везде где есть строки и пройдёт RTT. Возможность честно считать хоть 1/3*3 и получать честную 1, хоть 0.871827897987899987789371982391/2.

Минусы — кушает много байтиков, и работает в разы дольше чем обычная арифметика. Несмотря на минусы, иногда используется даже для числодробильных задач, которые на обычных даблах в разнос уходят.
Re[4]: Типы чисел в DSL
От: Alekzander  
Дата: 03.12.23 10:31
Оценка:
Здравствуйте, Marty, Вы писали:

A>>Я правильно понимаю, что ты посоветовал использовать number, и предложил имплементацию?


M>Типа того


A>>Если да, можно о ней хотя бы в двух словах рассказать, в частности о том, как сериализовать значения (записывать в sqlite)?


M>Есть метод std::string toString(int precision) const


M>Более того, я этот тип писал, чтобы а) хранить деньги без всяких округлений, любые суммы, б) хранить это в базе sqlite


А хранишь ты его как? Там есть STRICT Tables, и есть динамика. Первое или второе, и если первое, то какой sqlite'овский тип используешь? (Хотя я обычно за строгую динамическую типизацию, это тот редкий случай, когда я хочу полный контроль и STRICT Tables, т.к. работа с типами — часть моей прикладной задачи).
Re[5]: Типы чисел в DSL
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 03.12.23 11:57
Оценка:
Здравствуйте, Alekzander, Вы писали:

M>>Более того, я этот тип писал, чтобы а) хранить деньги без всяких округлений, любые суммы, б) хранить это в базе sqlite


A>А хранишь ты его как? Там есть STRICT Tables, и есть динамика. Первое или второе, и если первое, то какой sqlite'овский тип используешь? (Хотя я обычно за строгую динамическую типизацию, это тот редкий случай, когда я хочу полный контроль и STRICT Tables, т.к. работа с типами — часть моей прикладной задачи).


Я не помню деталей уже

Вроде бы NUMBER используется

Но что запомнилось, это то, что sqlite хранит всё всегда текстом. Хотя, может это и не так, и я ошибся
Маньяк Робокряк колесит по городу
Re: Типы чисел в DSL
От: Pavel Dvorkin Россия  
Дата: 03.12.23 15:44
Оценка: 3 (1) +1
Здравствуйте, Alekzander, Вы писали:

A>Возник вопрос на стыке проектирования, UX и БД )) Требуются ваши мнения.


A>Итак, что посоветуете для внутреннего представления чисел в памяти и хранения в sqlite? И какими типами это всё оформить для юзеров?


Ни в коей мере не считая себя специалистом в этом вопросе, выскажу мнение, которое наверняка уязвимо для критики.

Что знает обычный пользователь о данных ? Он знает то, чему его в школе учили. Что числа представляются с некоторой точностью. В десятичной, конечно, системе. Скажем, деньги (в рублях ) — с точностью 2 знака после запятой (копейки). И поэтому если 100 рублей разделить на троих, то каждый получит 33.33 рубля, а лишняя копейка пойдет в счет доходов аглицкого короля. Разделить ее на троих невозможно.

Соответственно, я бы ввел тип Number(I,F) — десятичное число, в котором может быть не более I знаков до запятой и ровно F знаков после.
И вариант его Number(,F) — ограничения на число знаков до запятой не вводится.

Операции производятся точно в смысле этих правил. Точно — в смысле как в школе учат, то есть по общепринятым в обычном мире правилам. При операндах разной точности результат имеет наибольшую точность.

100.00/3 == 33.33 (школьное деление с точностью до сотых)
100/3 == 3 (школьное деление целых с остатком, который игнорируем)
100.00/6 == 16.67 (школьное с точностью до сотых)
100/6.000 = 16.667 (школьное деление с точностью до тысячных)
100.0/6.000 = 16.667 (школьное деление с точностью до тысячных)
100.00/6.000 = 16.667 (школьное деление с точностью до тысячных)
100.000/6.000 = 16.667 (школьное деление с точностью до тысячных)
100.0000/6.000 = 16.6667 (школьное деление с точностью до десятитысячных)

P.S. Идея заимствована из PL/1. Там был тип DECIMAL FIXED(I,F)
P.P.S Разумеется, округление и контроль переполнения — под капотом, в интерпретаторе DSL.
With best regards
Pavel Dvorkin
Отредактировано 03.12.2023 15:48 Pavel Dvorkin . Предыдущая версия .
Re[2]: Типы чисел в DSL
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 03.12.23 18:42
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Посоветую взять JavaScript и всё. Число это просто double (64-битная плавающая точка).


А если понадобится финансовый инструмент?

Если один тип, то лучше закладываться на long double
Re[3]: Типы чисел в DSL
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 03.12.23 18:45
Оценка:
Здравствуйте, Alekzander, Вы писали:

Pzz>>Я бы шел от пользовательского интерфейса (который, в данном случае — твоя система типов, видимая пользователям). А когда там устаканится, уже думал бы о деталях реализации.


A>Идеальный GUI — это когда ты выбираешь тип number, а потом вводишь любые дробные и целые числа в пределах диапазона, и они складываются без потери точности.


Такого не бывает, к сожалению. Потому нужно представлять юзкейсы, какие вещи могут появиться в ui
Re[3]: Типы чисел в DSL
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 03.12.23 19:21
Оценка: +1
Здравствуйте, Pauel, Вы писали:

vsb>>Посоветую взять JavaScript и всё. Число это просто double (64-битная плавающая точка).


P>А если понадобится финансовый инструмент?


P>Если один тип, то лучше закладываться на long double


Нет, нет, только не это

#include <iostream>

int main()
{
  std::cout << "sizeof(long double)" << sizeof(long double) << "\n";
  std::cout << "sizeof(double)" << sizeof(double) << "\n";
  return 0;
}


x86-64 clang 13.0.0
sizeof(long double)16
sizeof(double)8


x86-64 gcc 13.2
sizeof(long double)16
sizeof(double)8


MSVC 2005
sizeof(long double)8
sizeof(double)8


MSVC 2017
sizeof(long double)8
sizeof(double)8


BCC 5.5 (да, древнее говно)
sizeof(long double)10
sizeof(double)8


Я когда-то весело попрыгал по граблям, когда прибор выдавал двоичные данные и там был long double, у меня был MSVC, а прошивку прибора писали на бомановском 3.1

Помимо несовместимости разных компиляторов, ты решишь, что 640long double уже точно хватит всем, но это не так, в лучшем случае грабли вылезут чуть попозже, если long double на твоей платформе больше обычного double.

В общем, очень плохая идея. Хуже всех остальных. И таки да, для бабла ничего лучше LongNumber не придумали, а в условном калькуляторе это никак не повлияет на производительность, а от кучи гемора тебя он избавит. Я бы его использовал и не парился
Маньяк Робокряк колесит по городу
Re[4]: Типы чисел в DSL
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 03.12.23 19:27
Оценка: +1
Здравствуйте, Pauel, Вы писали:

A>>Идеальный GUI — это когда ты выбираешь тип number, а потом вводишь любые дробные и целые числа в пределах диапазона, и они складываются без потери точности.


P>Такого не бывает, к сожалению. Потому нужно представлять юзкейсы, какие вещи могут появиться в ui


Почему не бывает? В LongNumber именно так и происходит
Маньяк Робокряк колесит по городу
Re[3]: Типы чисел в DSL
От: Pzz Россия https://github.com/alexpevzner
Дата: 04.12.23 10:23
Оценка:
Здравствуйте, Alekzander, Вы писали:

A>Идеальный GUI — это когда ты выбираешь тип number, а потом вводишь любые дробные и целые числа в пределах диапазона, и они складываются без потери точности. Но ты же сам пишешь, что "не получится". Тогда какой смысл со стороны GUI смотреть, не думая о реализуемости? Мне нужно оптимальное решение, т.е. наилучший GUI, но не вообще, а из тех, что технически реализуемы и не приведут к граблям.


А пользователи, вообще, поймут, что компьютерная арифметика имеет свои ограничения? А то, что ограничения могут быть разными, в зависимости от типа, они поймут?

Pzz>>А вот важны эти тонкости пользователям или нет — зависит от самих пользователей и от решаемых ими задач. И это надо как-то с ними обсудить.


A>Когда ты пишешь тул типа калькулятора, глупо обсуждать с юзерами, что они будут на нём считать, а что нет. Я просто предвижу, что рано или поздно кто-нибудь напишет ==, и это приведёт к проблемам. Кстати, может просто реализовать == через эпсилон, а вывод загрублять на один-два разряда по сравнению с родной точностью double'а того размера, который поддерживается в sqlite'е? Такое будет работать?


Калькулятор, кстати, вызывает на удивление мало лишних вопросов и пользователям, в среднем, хорошо понятен. Численный тип у него один, но как-то пользователи, в целом, успешно уживаются с его ограничениями.

Может тебе и сделать, как в калькуляторе?

Операция == в калькуляторе, насколько я понимаю, считает равными те числа, которе одинаково на экранчике отображаются.

A>А нельзя сделать вообще всё (универсальный number) на базе fixed point?


Ну, у него точность фиксируется в момент объявления типа. Для одних задач это ОК, для других — не ОК.

A>Если что, меня устроит ссылка на какой-нибудь фундаментальный труд "Типы чисел и их представления", если это где-то разжёвано, пойду просвещаться.


В древних языках было здоровое разнообразие. Теперь всё как-то упростилось
Re: Типы чисел в DSL
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.12.23 10:28
Оценка: 33 (2) +2
Здравствуйте, Alekzander, Вы писали:

A>Возник вопрос на стыке проектирования, UX и БД )) Требуются ваши мнения.


A>Мне нужно спроектировать DSL. С одной стороны, он должен быть строго типизирован (это требование), а с другой — этот тип появится на уровне GUI для массовых пользователей. А их, по возможности, хотелось бы не грузить разницей между int и double (не говоря про потерю точности), а дать им вместо этого некий универсальный тип number. С другой стороны, возможно, стоит один раз научить юзеров разнице между int и double, чем разруливать миллион неоднозначностей.

Вы забыли самое главное — а что за домен-то, для которого вы проектируете?
Вообще, что int, что double, для нормальных людей являются малопонятной наркоманией, которой нужно избегать как заразы.
Переполнения интов и потери точности для double ведут себя в бытовых сценариях настолько противоестественно, что даже программисты часто ошибаются.

Пункт 1: double не нужен вообще ни для чего, кроме научных расчётов. Если ваша предметная область — не про физику/математику, то забудьте про дабл как про страшный сон.
Пункт 2: так называемые "целые" двоичной разрядности имеют только одно полезное свойство: они быстро обрабатываются компьютером.
Пункт 3: Если в вашей предметной области нет расчётов с триллионами значений, то длинные десятичные будут гораздо более адекватным выбором.
Если есть — то тогда вам пригодятся ограниченные десятичные, которые лишь чуть-чуть медленнее интов, зато ведут себя предсказуемо.

Так что я бы оставил в языке понятие number с известным количеством цифр после запятой (и неограниченным — до запятой).
Если окажется, что такие длинные числа приводят на практике к нехорошестям, то оптимизировал бы язык, заменив в нём представление number на ограниченное.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[13]: Типы чисел в DSL
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.12.23 10:38
Оценка: +2
Здравствуйте, Marty, Вы писали:
M>Мой пример относится к любому финансовому софту. Ну, кроме такого, который написать, запустить, и навсегда забыть. Иначе через 5-10-20 лет это вылезет в виде какой-то внезапной жопы, и что-то сделать уже будет малореально. Это ещё если ты из-за каких-нибудь незамеченных округлений не влетишь на штрафы от фискальных органов
Вылезет не через 5 лет, а немедленно. Те же 0.1 + 0.2 в дабле сложил — и приплызд в неожиданных местах.
Я вообще не понимаю, откуда взялась такая дискуссия в 2023 году. Программисты ещё полсотни лет назад знали, что деньги в даблах хранить нельзя ни в каком случае.

M>А в финансах вообще мало делят, там всё больше прибавляют и приумножают

В том то и дело, что ТС не указал тематику языка. Потому что в финансах обычно операции не такие, как в алгебре. Например, есть операции вроде "есть набор из N чисел, нужно начислить к ним 21.5% налога, и раскидать на N пунктов так, чтобы погрешность в каждой строке и погрешность суммы не превышала 1 младший разряд".

M>>>А вообще, тех, кто считает деньги в double — их надо сразу расстреливать

Не, мы против смертной казни. Принудительные работы в саппорте до пяти лет. Если группой по предварительному сговору, либо с использованием служебного положения — то от семи до десяти.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Типы чисел в DSL
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 04.12.23 11:26
Оценка:
Здравствуйте, Sinclair, Вы писали:


S>Так что я бы оставил в языке понятие number с известным количеством цифр после запятой (и неограниченным — до запятой).


У меня в реализации почти так и сделано. Т.е. сложение/вычитание — не меняют числа знаков после запятой, умножение — даёт сумму знаков после запятой множителей (и потом можно округлить, если очень надо), для деления есть static поле precision, до которого производится деление через operator/(). Если надо разделить точнее или грубее — есть специальные методы. Не помню, сделано или нет, но наверно имеет смысл по дефолту делить с точностью precision+1, и затем округлять последний знак дефолтным способом (вот такого статик поля у меня точно сейчас нет, скорее всего Rounding::math используется, если сделано с округлением последнего знака)
Маньяк Робокряк колесит по городу
Re[4]: Типы чисел в DSL
От: Alekzander  
Дата: 04.12.23 18:35
Оценка:
Здравствуйте, Pzz, Вы писали:

A>>Когда ты пишешь тул типа калькулятора, глупо обсуждать с юзерами, что они будут на нём считать, а что нет. Я просто предвижу, что рано или поздно кто-нибудь напишет ==, и это приведёт к проблемам. Кстати, может просто реализовать == через эпсилон, а вывод загрублять на один-два разряда по сравнению с родной точностью double'а того размера, который поддерживается в sqlite'е? Такое будет работать?


Pzz>Калькулятор, кстати, вызывает на удивление мало лишних вопросов и пользователям, в среднем, хорошо понятен. Численный тип у него один, но как-то пользователи, в целом, успешно уживаются с его ограничениями.


Pzz>Может тебе и сделать, как в калькуляторе? Операция == в калькуляторе, насколько я понимаю, считает равными те числа, которе одинаково на экранчике отображаются.


Мне как-то не доводилось видеть калькулятор с ==. Я даже не поленился, поднял Жёлтый Мануал от МК-52 (самого продвинутого калькулятора, который знал). И там нет никакого ==, а есть только классика: сравнение с нулём. Что делается проверкой на 0 одного знакового бита и проверкой на 0 всех битов. Поэтому я даже не знаю, "как в калькуляторе" это как где?

A>>А нельзя сделать вообще всё (универсальный number) на базе fixed point?

Pzz>Ну, у него точность фиксируется в момент объявления типа. Для одних задач это ОК, для других — не ОК.

Я понял, спасибо.
Re[2]: Типы чисел в DSL
От: Alekzander  
Дата: 04.12.23 18:56
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Вы забыли самое главное — а что за домен-то, для которого вы проектируете?


Мы тут недавно по соседству обсуждали Outlook, и, в частности, вот этот диалог:



Какой там домен? Вот и у меня, будем считать, такой же. Домен "Универсальный", как сказали бы маркетологи.

S>Вообще, что int, что double, для нормальных людей являются малопонятной наркоманией, которой нужно избегать как заразы.


Это-то я хорошо понимаю. Но вот столкнувшись с необходимостью как-то имплементировать, я понял, что это не так-то просто.

S>Переполнения интов и потери точности для double ведут себя в бытовых сценариях настолько противоестественно, что даже программисты часто ошибаются.


S>Пункт 1: double не нужен вообще ни для чего, кроме научных расчётов. Если ваша предметная область — не про физику/математику, то забудьте про дабл как про страшный сон.

S>Пункт 2: так называемые "целые" двоичной разрядности имеют только одно полезное свойство: они быстро обрабатываются компьютером.
S>Пункт 3: Если в вашей предметной области нет расчётов с триллионами значений, то длинные десятичные будут гораздо более адекватным выбором.
S>Если есть — то тогда вам пригодятся ограниченные десятичные, которые лишь чуть-чуть медленнее интов, зато ведут себя предсказуемо.

S>Так что я бы оставил в языке понятие number с известным количеством цифр после запятой (и неограниченным — до запятой).

S>Если окажется, что такие длинные числа приводят на практике к нехорошестям, то оптимизировал бы язык, заменив в нём представление number на ограниченное.

Понял, принял. Буду думать ))
Отредактировано 04.12.2023 19:26 Alekzander . Предыдущая версия .
Re[4]: Типы чисел в DSL
От: Alekzander  
Дата: 04.12.23 19:22
Оценка:
Здравствуйте, Marty, Вы писали:

M>x86-64 clang 13.0.0

M>x86-64 gcc 13.2
M>MSVC 2005
M>MSVC 2017
M>BCC 5.5 (да, древнее говно)

Ограничивающим фактором является, скорее, вот это: https://www.sqlite.org/datatype3.html

REAL. The value is a floating point value, stored as an 8-byte IEEE floating point number.


Я так понял, другого double у них для нас нет ))

А компиляторы, что ж... Всегда можно обойти эти проблемы через какой-нибудь __тип. Тем более, никто в здравом уме не будет писать в коде long double без тайпдефов из-за этих милых особенностей (если ты об этом).

M>Я когда-то весело попрыгал по граблям, когда прибор выдавал двоичные данные и там был long double, у меня был MSVC, а прошивку прибора писали на бомановском 3.1


M>Помимо несовместимости разных компиляторов, ты решишь, что 640long double уже точно хватит всем, но это не так, в лучшем случае грабли вылезут чуть попозже, если long double на твоей платформе больше обычного double.


M>В общем, очень плохая идея. Хуже всех остальных. И таки да, для бабла ничего лучше LongNumber не придумали, а в условном калькуляторе это никак не повлияет на производительность, а от кучи гемора тебя он избавит. Я бы его использовал и не парился


Послушав всех, я склоняюсь к двум типам: number и currency (название условно).

number как в JS'е (т.е. sqlit'овский 8-байтовый REAL), но с принудительным выводом на разряд меньше (если форматирование не задано) и с эпсилоновской реализацией ==.

currency — sqlit'овский 8-байтовый INTEGER, который fixed point и в сто раз больше + код валюты. "Количество" считаем кодом валюты. (На уровне UI можно их или разделить, или придумать удачное название типа "Currency or quantity" ).

При попытках действий, которые выльются в преобразования, проверять, что currency и currency можно только складывать, вычитать и умножать при совместимом коде (складывать и вычитать строго одинаковые коды, а умножать только валюту на количество или количество на количество). В противном случае — выдавать предупреждение.

Что может пойти не так? (Кроме как всё, само собой).
Отредактировано 04.12.2023 19:23 Alekzander . Предыдущая версия .
Re[5]: Типы чисел в DSL
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 04.12.23 19:46
Оценка:
Здравствуйте, Alekzander, Вы писали:


A>А компиляторы, что ж... Всегда можно обойти эти проблемы через какой-нибудь __тип. Тем более, никто в здравом уме не будет писать в коде long double без тайпдефов из-за этих милых особенностей (если ты об этом).


Или нельзя найти какой-нибудь __тип. Потому что его нет. Найди мне, каким именем 10 байт long double в MSVC называется. А то я хранил его в массиве байт и ручками в double конвертил.


A>currency — sqlit'овский 8-байтовый INTEGER, который fixed point и в сто раз больше + код валюты. "Количество" считаем кодом валюты. (На уровне UI можно их или разделить, или придумать удачное название типа "Currency or quantity" ).


Некоторые акции торгуются по 0.000001 руб за штуку. Не ложится в твой currency. Но можно увеличить размер дробной части, до 6ти знаков, например. Правда, при этом лучше надеяться, что никогда не появится акций с ценой с большим количеством знаков. 0x7FFFFFFFFFFFFFFF/100000 = 92 233 720 368 547 руб. Ну, в принципе, для домашней бухгалтерии хватит. Только не пиши серьёзный софт


A>При попытках действий, которые выльются в преобразования, проверять, что currency и currency можно только складывать, вычитать и умножать при совместимом коде (складывать и вычитать строго одинаковые коды, а умножать только валюту на количество или количество на количество).


Для currency это в любом случае неплохо сделать, сделав currency отдельным типом.


A>В противном случае — выдавать предупреждение.


Если пользователю — то да, а так, в коде — только кидать исключение, ибо нефик


A>Что может пойти не так? (Кроме как всё, само собой).


Например, тебе понравится и ты решишь использовать свой fixed point ещё для чего-то. И забудешь, что при умножении надо будет удалять разряды справа. Или, в целом, произведение будет представимо в твоём fixed point, но в процессе умножения до нормализации разрядов произведение таки вылезает за допустимый в int64 диапазон.

Кстати, а дробная часть у тебя как, двоичная или десятичная будет?

В общем, удачки тебе с fixed point
Маньяк Робокряк колесит по городу
Re[3]: Типы чисел в DSL
От: Sinclair Россия https://github.com/evilguest/
Дата: 05.12.23 08:43
Оценка: 9 (1)
Здравствуйте, Alekzander, Вы писали:
A>Какой там домен? Вот и у меня, будем считать, такой же. Домен "Универсальный", как сказали бы маркетологи.
Ну вот обратите внимание — авторы Outlook уже в доисторические времена не стали заморачивать людей интами и флоатами. Нумбер и точность — вот наши друзья!

A>Это-то я хорошо понимаю. Но вот столкнувшись с необходимостью как-то имплементировать, я понял, что это не так-то просто.

Ну вариантов тут несколько.
Помимо уже обсуждавшихся чисел с фиксированной точностью, есть упомянутый одним из коллег Rational.
Он ведёт себя прилично везде, кроме возведения в нецелые степени и тригонометрии.
У него преимущество перед decimal — в отсутствии маеты с разрядностью. Например, нам не нужно ни заставлять человека указывать, сколько знаков после запятой будет у X. И не нужно думать, сколько знаков после запятой будет у z, который равен x / y. Или как нам сделать что-то типа x = x * y, если у игрека после запятой не ноль знаков.
Недостаток у него — в отсутствии разрядности. Number(2) всегда превращается в строку с 2мя знаками, даже если внутри него целое число. И округляется всегда до запрошенного количества знаков.
А Rational нужно округлять вручную, и разрядность указывать при выводе.

S>>Переполнения интов и потери точности для double ведут себя в бытовых сценариях настолько противоестественно, что даже программисты часто ошибаются.


S>>Пункт 1: double не нужен вообще ни для чего, кроме научных расчётов. Если ваша предметная область — не про физику/математику, то забудьте про дабл как про страшный сон.

S>>Пункт 2: так называемые "целые" двоичной разрядности имеют только одно полезное свойство: они быстро обрабатываются компьютером.
S>>Пункт 3: Если в вашей предметной области нет расчётов с триллионами значений, то длинные десятичные будут гораздо более адекватным выбором.
S>>Если есть — то тогда вам пригодятся ограниченные десятичные, которые лишь чуть-чуть медленнее интов, зато ведут себя предсказуемо.

S>>Так что я бы оставил в языке понятие number с известным количеством цифр после запятой (и неограниченным — до запятой).

S>>Если окажется, что такие длинные числа приводят на практике к нехорошестям, то оптимизировал бы язык, заменив в нём представление number на ограниченное.

A>Понял, принял. Буду думать ))
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[6]: Типы чисел в DSL
От: Alekzander  
Дата: 06.12.23 04:31
Оценка:
Здравствуйте, Marty, Вы писали:

M>Некоторые акции торгуются по 0.000001 руб за штуку. Не ложится в твой currency. Но можно увеличить размер дробной части, до 6ти знаков, например. Правда, при этом лучше надеяться, что никогда не появится акций с ценой с большим количеством знаков. 0x7FFFFFFFFFFFFFFF/100000 = 92 233 720 368 547 руб. Ну, в принципе, для домашней бухгалтерии хватит. Только не пиши серьёзный софт


Так они и продаются, наверно, пакетами тысяч в десять или сто при такой-то цене.

A>>Что может пойти не так? (Кроме как всё, само собой).


M>Кстати, а дробная часть у тебя как, двоичная или десятичная будет?


Не понял вопроса. А просто считать в сотых, это двоичная или десятичная? И как выглядит другая?
Re[7]: Типы чисел в DSL
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 06.12.23 04:58
Оценка: 9 (1)
Здравствуйте, Alekzander, Вы писали:

A>Так они и продаются, наверно, пакетами тысяч в десять или сто при такой-то цене.


Да, они продаются лотами. Но оперировать стоимостью одной акции всё равно придётся


M>>Кстати, а дробная часть у тебя как, двоичная или десятичная будет?


A>Не понял вопроса. А просто считать в сотых, это двоичная или десятичная? И как выглядит другая?


Это десятичная — умножаешь/делишь на сто. Сдвигами не получится. Двоичная — это когда у тебя после точки идут 1/2, 1/4, 1/8, 1/16 и тп. 0.1 ты с двоичной дробной частью не сможешь получить.

А с десятичной дробной частью обнулить дробную часть просто по битовой маске не получится

По итогу если с десятичной дробной частью — это тот же BigDecimal, только не Big. Получаешь геморои от того, что дробь десятичная, а профиты от Big — не получаешь.

Ну, в общем, если будешь decimal fixed point на целых делать, приходи к нам с геморроями, поржем
Маньяк Робокряк колесит по городу
Re: Типы чисел в DSL
От: Ночной Смотрящий Россия  
Дата: 19.12.23 07:54
Оценка: 12 (1)
Здравствуйте, Alekzander, Вы писали:

A>Возник вопрос на стыке проектирования, UX и БД )) Требуются ваши мнения.


Ты не с того начал. Начать следует с описания юзкейсов и нефункциональных требований. Скорее всего после этого у тебя уже куча вариантов отсеется. После этого из оставшихся вариантов делаешь примеры кусочков на гипотетическом DSL и идешь с ними к целевой аудитории.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[2]: Типы чисел в DSL
От: Alekzander  
Дата: 19.12.23 15:55
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

A>>Возник вопрос на стыке проектирования, UX и БД )) Требуются ваши мнения.


НС>Ты не с того начал. Начать следует с описания юзкейсов и нефункциональных требований. Скорее всего после этого у тебя уже куча вариантов отсеется. После этого из оставшихся вариантов делаешь примеры кусочков на гипотетическом DSL и идешь с ними к целевой аудитории.


Я уже выше отписал, что это, как говорится, "инструмент общего назначения". Как калькулятор. Даже не сам калькулятор (для калькуляторного GUI юзкейсы имеют смысл), а калькуляторный движок под капотом.
Re[3]: Типы чисел в DSL
От: Ночной Смотрящий Россия  
Дата: 19.12.23 18:06
Оценка: :)
Здравствуйте, Alekzander, Вы писали:

НС>>Ты не с того начал. Начать следует с описания юзкейсов и нефункциональных требований. Скорее всего после этого у тебя уже куча вариантов отсеется. После этого из оставшихся вариантов делаешь примеры кусочков на гипотетическом DSL и идешь с ними к целевой аудитории.

A>Я уже выше отписал, что это, как говорится, "инструмент общего назначения".

Ты уж определись, DSL у тебя или универсальный язык. Если второе — ничего изобретать не нужно, берешь любой популярный строго-типизированный язык — Java, C# и т.п.

A>Как калькулятор. Даже не сам калькулятор (для калькуляторного GUI юзкейсы имеют смысл), а калькуляторный движок под капотом.


Строго типизированный калькулятор?
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re: Типы чисел в DSL
От: Sinclair Россия https://github.com/evilguest/
Дата: 19.01.24 06:37
Оценка: 15 (1)
Здравствуйте, Alekzander, Вы писали:
A>Итак, что посоветуете для внутреннего представления чисел в памяти и хранения в sqlite? И какими типами это всё оформить для юзеров?
Внезапно столкнулся с такой же задачей.
Пока что кажется, что лучше всего — что-то вроде дотнетного Decimal.
Делать "резиновый" scale точно нельзя — потому что тогда 1/3 порождает число бесконечной длины.
Делать "резиновым" precision можно, но пока непонятно, нужно ли оно на практике. Это тип данных не для решения всяких уравнений, где, скажем, надо делить очень большое число на очень маленькое, а для деловых/финансовых расчётах.
Там верх сложности — это какой-нибудь StDev, где надо вычитать квадрат суммы из суммы квадратов, и WeightedAverage, где нужно делить сумму произведений на целое число.
Допустим, длина коллекции у нас порядка 2L, размеры элементов — порядка 2N. Итого, сумма квадратов потребует 2N+L бит.
То есть, скажем, коллекция в миллион элементов (L=20) и значениями, скажем, сто триллионов (N~47 бит) получаем 114 бит.
114битное число содержит до 35 десятичных цифр. Если мы хотим все эти цифры пустить на точность числа между 0 и 1, то нам не нужен scale больше 34. То есть для него достаточно 6 бит. Плюс знак — 1 бит.
Итого, получилось 121 бит — влезаем в 128. В принципе, 6 бит хватит и для бОльших scale. В 128 бит можно запихать до 121 бит точности, 1 бит знака, 6 бит scale. Но, наверное, производительность будет подтормаживать при таком плотном расположении.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.