Re[6]: Арифметическое переполнение
От: AlexRK  
Дата: 22.02.14 12:25
Оценка:
Здравствуйте, Mystic, Вы писали:

M>Заранее выбирать тип range для i такой, чтобы он вмещал все разумные значения. Например, выделение памяти. Если мы заранее знаем, что не будут выделяться фрагменты более 100M, мы можем указать диапазон с некоторым запасом, скажем 1G, чтобы (A) иметь свободу маневра и (B) исключить переполнение при элементарных операциях.


Да, что-то в этом направлении. Но все равно руками контракты писать придется? А если там формула Result:=((A+B)/(B*C-D))^E ? Как программист сможет выбрать "нормальный вариант с запасом" без того, чтобы сесть и выводить математические диапазоны?
Re[7]: Арифметическое переполнение
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 22.02.14 12:33
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Здравствуйте, Mystic, Вы писали:


M>>Заранее выбирать тип range для i такой, чтобы он вмещал все разумные значения. Например, выделение памяти. Если мы заранее знаем, что не будут выделяться фрагменты более 100M, мы можем указать диапазон с некоторым запасом, скажем 1G, чтобы (A) иметь свободу маневра и (B) исключить переполнение при элементарных операциях.


ARK>Да, что-то в этом направлении. Но все равно руками контракты писать придется? А если там формула Result:=((A+B)/(B*C-D))^E ? Как программист сможет выбрать "нормальный вариант с запасом" без того, чтобы сесть и выводить математические диапазоны?


Если брать исходники Ada, то там стараются использовать диапазоны. Соответственно, при объявлении переменных A, B, C, D, E я должен задаться вопросом, а что хранится в этих переменных? Если A это численность студентов в группе, то мне надо писать range 0 .. 99. Если B это голубой цвет, то range 0..255. С одной стороны лишняя работа. С другой стороны, статический анализ поможет раньше выловить разные баги и опечатки.
Re[5]: Арифметическое переполнение
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 22.02.14 12:41
Оценка:
Здравствуйте, AlexRK, Вы писали:

K>>Полагаю, этот же подход можно перенести в языки высокого уровня: по умолчанию результат арифметических операций, которые могут привести к переполнению, должен возвращаться в виде значения большего разряда. То есть складываем два числа int32, результат получаем в int64.

K>>При этом придётся убрать из языка неявные приведения типа в арифметических операциях (вариант: сделать включение/отключение неявных преобразований опциональным, как checked в C#).

ARK>Да, абсолютно верно, речь именно об этом. В принципе при сложении двух Int32 для результата достаточно одного лишнего разряда, чтобы ошибки не возникло (Int33 ). Но возникает масса проблем с циклами, да и просто с вызовом методов — все будут требовать специфические условия для себя. Вот я и интересуюсь, может есть какие-то интересные подходы...


И такой бит есть. Он правда отдельно расположен, обычно в флаговом регистре. На тех нескольких платформах, на которых я поработал, он везде есть. Единственное, что меня всегда удивляло, так это то, что в языке C/C++ нет какой-то инструкции/конструкции, которая бы помогала определять факт переполнения, вроде же "высокоуровневый ассемблер". Наверно на PDP, или на чем там первый C делали, не было такого флага.

При наличии такой конструкции можно было бы либо игнорировать переполнение/заём, если алгоритму безразличен; обработать его, как надо, если это важно; или бросить исключение (C++), если не знаешь, что делать.
Маньяк Робокряк колесит по городу
Re[8]: Арифметическое переполнение
От: AlexRK  
Дата: 22.02.14 12:44
Оценка:
Здравствуйте, Mystic, Вы писали:

ARK>>Да, что-то в этом направлении. Но все равно руками контракты писать придется? А если там формула Result:=((A+B)/(B*C-D))^E ? Как программист сможет выбрать "нормальный вариант с запасом" без того, чтобы сесть и выводить математические диапазоны?


M>Если брать исходники Ada, то там стараются использовать диапазоны. Соответственно, при объявлении переменных A, B, C, D, E я должен задаться вопросом, а что хранится в этих переменных? Если A это численность студентов в группе, то мне надо писать range 0 .. 99. Если B это голубой цвет, то range 0..255. С одной стороны лишняя работа. С другой стороны, статический анализ поможет раньше выловить разные баги и опечатки.


Диапазоны входных параметров — это еще полбеды. А вот с возвращаемыми значениями все куда веселее. Для формулы, которую я привел выше, диапазон уже совсем не очевиден. Можно его вывести автоматически, но тогда мы выставляем наружу сильную зависимость от реализации. Чуть изменили формулу — и все.

Да еще и с циклами большой вопрос... С ними проблемы предупреждения переполнения многократно хуже.

Видимо, я хочу невозможного и только искусственный интеллект может помочь.
Re[6]: Арифметическое переполнение
От: AlexRK  
Дата: 22.02.14 12:47
Оценка:
Здравствуйте, Marty, Вы писали:

M>И такой бит есть. Он правда отдельно расположен, обычно в флаговом регистре. На тех нескольких платформах, на которых я поработал, он везде есть. Единственное, что меня всегда удивляло, так это то, что в языке C/C++ нет какой-то инструкции/конструкции, которая бы помогала определять факт переполнения, вроде же "высокоуровневый ассемблер". Наверно на PDP, или на чем там первый C делали, не было такого флага.


Это только для сложения достаточно лишнего бита. А для умножения двух N-разрядных чисел для результата нужно уже 2N разрядов.

M>При наличии такой конструкции можно было бы либо игнорировать переполнение/заём, если алгоритму безразличен; обработать его, как надо, если это важно; или бросить исключение (C++), если не знаешь, что делать.


Ну, вообще говоря, тема посвящена не обработке переполнения постфактум, а вопросу предупреждения переполнения на этапе компиляции.
Re[9]: Арифметическое переполнение
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 22.02.14 13:10
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Диапазоны входных параметров — это еще полбеды. А вот с возвращаемыми значениями все куда веселее. Для формулы, которую я привел выше, диапазон уже совсем не очевиден. Можно его вывести автоматически, но тогда мы выставляем наружу сильную зависимость от реализации. Чуть изменили формулу — и все.


ARK>Да еще и с циклами большой вопрос... С ними проблемы предупреждения переполнения многократно хуже.


ARK>Видимо, я хочу невозможного и только искусственный интеллект может помочь.


Возвращаемые значения они же тоже что-то значат. Если функция возвращает количество фигур на шахматной доске, то ее результат вполне можно описать как range 2..32. Конечно, нужны достаточно выразительные средства для контрактов. Особенно если позиция хранится в битовых масках.

А с другой стороны, а это так надо? Все таки критического кода не так уж и много, и если это действительно надо, то надо заморочиться.
Re[7]: Арифметическое переполнение
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 22.02.14 13:31
Оценка:
Здравствуйте, AlexRK, Вы писали:

M>>При наличии такой конструкции можно было бы либо игнорировать переполнение/заём, если алгоритму безразличен; обработать его, как надо, если это важно; или бросить исключение (C++), если не знаешь, что делать.


ARK>Ну, вообще говоря, тема посвящена не обработке переполнения постфактум, а вопросу предупреждения переполнения на этапе компиляции.


По поводу того, что тема посвящена исключительно отлову на этапе компиляции — это как-то не очевидно из исходного сообщения.

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

Или я что-то не понимаю?
Маньяк Робокряк колесит по городу
Re[10]: Арифметическое переполнение
От: AlexRK  
Дата: 22.02.14 13:39
Оценка:
Здравствуйте, Mystic, Вы писали:

M>Возвращаемые значения они же тоже что-то значат. Если функция возвращает количество фигур на шахматной доске, то ее результат вполне можно описать как range 2..32. Конечно, нужны достаточно выразительные средства для контрактов. Особенно если позиция хранится в битовых масках.


Да, действительно. Хотел сейчас привести спорные примеры из дотнета, но что-то с налету не нашел. Width/Height из контролов — диапазоны определяются размерами экрана. Controls.Count, TabIndex — максимальное количество контролов на форме. Правда, сейчас этим не заморачиваются, везде просто int.

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

M>А с другой стороны, а это так надо? Все таки критического кода не так уж и много, и если это действительно надо, то надо заморочиться.


Надо ли — философский вопрос. В принципе, много чего не надо. Вон на Ц пишут операционные системы, а в нем ничего нет.
Re[8]: Арифметическое переполнение
От: AlexRK  
Дата: 22.02.14 13:43
Оценка:
Здравствуйте, Marty, Вы писали:

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


Согласен, первый пост не вполне очевиден в этом плане.

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


M>Или я что-то не понимаю?


Да нет, фишка как раз в том, что в рантайме ничего не решается. Отсутствие ошибок гарантируется на этапе компиляции. Но, конечно, все функции в качестве входных и выходных параметров используют не простые типы вроде int, а ограниченные диапазоны (0..10, -1000..10000 и т.п.). Таким образом, например, если мы складываем не больше 10 чисел, каждое из которых не больше 100 и не меньше 0, то результат гарантировано будет лежать в диапазоне 0..1000.
Re: Арифметическое переполнение
От: Pavel Dvorkin Россия  
Дата: 23.02.14 06:26
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Может быть есть иные подходы обработки переполнений?


Для целых чисел — не допускать их вообще. Используйте арифметику с соответствующей длиной операндов.

>Хочется вариант с полной скоростью и полной надежностью


И будет он.
With best regards
Pavel Dvorkin
Re[2]: Арифметическое переполнение
От: AlexRK  
Дата: 23.02.14 06:52
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

ARK>>Может быть есть иные подходы обработки переполнений?

PD>Для целых чисел — не допускать их вообще. Используйте арифметику с соответствующей длиной операндов.

А можно немного подробнее? Что вы имеете в виду под "арифметикой с соответствующей длиной операндов"?
Re: Арифметическое переполнение
От: NeoCode  
Дата: 23.02.14 09:35
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Думаю над сабжевым вопросом. Существующие языки программирования разбираются с переполнением по-разному:


Я в своем разрабатываемом языке программирования принял стратегию С/С++ с возможностью использовать альтернативные режимы явно:
Из C#: checked/unchecked
И режим насыщения sated/unsated (т.е. для байта например sated { 255+1 } == 255 )
разумеется, в такие блоки можно заключать фрагменты кода любого размера, хоть целые модули.
Re[2]: Арифметическое переполнение
От: AlexRK  
Дата: 23.02.14 09:46
Оценка:
Здравствуйте, NeoCode, Вы писали:

NC>Я в своем разрабатываемом языке программирования принял стратегию С/С++ с возможностью использовать альтернативные режимы явно:


Покажете язык-то? Я интересуюсь языками программирования.

NC>Из C#: checked/unchecked

NC>И режим насыщения sated/unsated (т.е. для байта например sated { 255+1 } == 255 )
NC>разумеется, в такие блоки можно заключать фрагменты кода любого размера, хоть целые модули.

Понятно. В принципе, выбранные решения просты в реализации.
А я тяготею к математической корректности в условиях ограничений реальной аппаратуры.
Re: Арифметическое переполнение
От: minorlogic Украина  
Дата: 23.02.14 09:49
Оценка:
еще есть вариант не выполнять все операции по месту а только накапливать буффер операций, и выводить результат когда он нужен по факту.

Также есть комбинированные подходы , хранить дроби неограниченной длниы для простых операций и т.д
... << RSDN@Home 1.2.0 alpha 5 rev. 1539>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[3]: Арифметическое переполнение
От: Pavel Dvorkin Россия  
Дата: 23.02.14 09:49
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>А можно немного подробнее? Что вы имеете в виду под "арифметикой с соответствующей длиной операндов"?


Если ожидается, что значения не выйдут за пределы (беру знаковый случай) -2^15..2^15-1 — хватит и short, хотя, возможно, стоит все же использовать int, так как short для 32/64-битного процессора не родной
Если в этом нет уверенности, но ожидается, что значения не выйдут за пределы -2^31..2^31 -1 — хватит int
Если и это под вопросом, но ожидается, что значения не выйдут за пределы -2^63..2^63 -1 — брать long

Если же целые числа могут выйти за пределы -2^63..2^63 -1 — задать себе вопрос, что это за такие целые (точные!) числа и почему они должны быть целыми.

А для вещественных чисел в случае Windows есть __try — _except. Не знаю насчет платформонезависимого варианта.
With best regards
Pavel Dvorkin
Re[2]: Арифметическое переполнение
От: AlexRK  
Дата: 23.02.14 10:05
Оценка:
Здравствуйте, minorlogic, Вы писали:

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


Если я правильно понимаю, это уже некая надстройка, подход скорее для высокоуровневых пакетов типа матлаба. Вряд ли такое применимо там, где требуется производительность.

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


Хранение рациональных чисел в виде простых дробей? ИМХО, это из той же оперы. Да и к переполнению вряд ли имеет отношение.
Re[4]: Арифметическое переполнение
От: AlexRK  
Дата: 23.02.14 10:08
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Если ожидается, что значения не выйдут за пределы (беру знаковый случай) -2^15..2^15-1 — хватит и short, хотя, возможно, стоит все же использовать int, так как short для 32/64-битного процессора не родной

PD>Если в этом нет уверенности, но ожидается, что значения не выйдут за пределы -2^31..2^31 -1 — хватит int
PD>Если и это под вопросом, но ожидается, что значения не выйдут за пределы -2^63..2^63 -1 — брать long

А, вы об этом.
Меня интересует немного другое — корректность программ более сильного вида, а именно формальная. Т.е. отсутствие переполнений, гарантированное компилятором.
Re[5]: Арифметическое переполнение
От: Pavel Dvorkin Россия  
Дата: 23.02.14 10:16
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Меня интересует немного другое — корректность программ более сильного вида, а именно формальная. Т.е. отсутствие переполнений, гарантированное компилятором.


А зачем решать проблему, если можно ее легко обойти ?
With best regards
Pavel Dvorkin
Re[6]: Арифметическое переполнение
От: AlexRK  
Дата: 23.02.14 10:26
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>А зачем решать проблему, если можно ее легко обойти ?


Ну, это вопрос философский.

Лично мне нравится такая цель — создание корректного ПО. Гарантированно корректного, а не с некоторой вероятностью. Под корректностью в данном контексте я понимаю отсутствие ошибок времени исполнения.
Если можно достичь этого, то почему бы и нет?
Re[7]: Арифметическое переполнение
От: Pavel Dvorkin Россия  
Дата: 23.02.14 10:57
Оценка:
Здравствуйте, AlexRK, Вы писали:

PD>>А зачем решать проблему, если можно ее легко обойти ?


ARK>Ну, это вопрос философский.


Не согласен. Если есть способ избавиться от проблемы, то ИМХО решать ее не надо, а надо именно избавиться. Других проблем хватит, от которых избавиться так просто не удастся.

ARK>Лично мне нравится такая цель — создание корректного ПО. Гарантированно корректного, а не с некоторой вероятностью. Под корректностью в данном контексте я понимаю отсутствие ошибок времени исполнения.


А в том, что я предложил, именно эта цель и достигается. Дело в том, что абстрактная задача избавиться от переполнений вообще не решается, так как размер памяти, отводимой для чисел, ограничен всегда, а значит можно придумать абстрактную ситуацию, когда переполнение все равно возникнет. Однако из этого вовсе не следует, что если в реальной ситуации можно сделать так, чтобы оно не возникало, то реально работающему программисту нужно обязательно поразмышлять над этой абстрактной и в практике не существующей ситуацией.

Мало ли какие абстрактные ситуации могут быть... Например, можно пообсуждать, как обеспечить работу программы при адресном пространстве в 64 Кбайта, каким оно и было во времена первых микропроцессоров. Тогда для того, чтобы программы уложить в эту память, придуманы были различные методики, о которых сейчас никто уже и не помнит, так как проблема самоликвидировалась. Нет ее, и решать незачем.
With best regards
Pavel Dvorkin
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.