Проблемы с Uint64
Модератор: Модераторы
Проблемы с Uint64
Здравствуйте. Надавно стал замечать, что в ранее работавшем коде стали появляться логические ошибки. После дебага оказалось что ошибка возникает в результат выполнения арифметических операций с двумя переменными типа Uint64. Например 110840 - 110842 = 18446744073709551614. Как я понимаю вычитание беззнаковых интерпретирует результат вычитание как такое же беззнаковое число. Но ранее этого небыло. Что я мог сломать и откуда взялась такая странная логика? Lazarus 1.4.4 оптимизация O3
- Лекс Айрин
- долгожитель
- Сообщения: 5723
- Зарегистрирован: 19.02.2013 16:54:51
- Откуда: Волгоград
- Контактная информация:
А если отключить оптимизацию?
Добавлено спустя 4 минуты 56 секунд:
Вообще, результат законен. При вычитании большего из меньшего и должно получиться такое громадное число, если не используется информация о переполнении регистра. Есть подозрение, что излишне ретивый оптимизатор эту проверку убирает, считая, что за этим должен следить программист.
Добавлено спустя 4 минуты 56 секунд:
Вообще, результат законен. При вычитании большего из меньшего и должно получиться такое громадное число, если не используется информация о переполнении регистра. Есть подозрение, что излишне ретивый оптимизатор эту проверку убирает, считая, что за этим должен следить программист.
Например 110840 - 110842 = 18446744073709551614.
А что, по-вашему, должно являться результатом вычитания этих чисел в UInt64?
Дож писал(а):А что, по-вашему, должно являться результатом вычитания этих чисел в UInt64?
должно получится -2 и ранее получалось
- Лекс Айрин
- долгожитель
- Сообщения: 5723
- Зарегистрирован: 19.02.2013 16:54:51
- Откуда: Волгоград
- Контактная информация:
CRobin, вообще-то, это было из-за того, что переменные неявно превращались в знаковые, а потом, если надо, обратно.
Лекс Айрин писал(а):CRobin, вообще-то, это было из-за того, что переменные неявно превращались в знаковые, а потом, если надо, обратно.
Я ничего не менял в коде. Могу только вспомнить восстановление LPI и LPS файлов после падения диска, может быть там были объявлены какие то опции компилятора?
- Лекс Айрин
- долгожитель
- Сообщения: 5723
- Зарегистрирован: 19.02.2013 16:54:51
- Откуда: Волгоград
- Контактная информация:
CRobin, ты нет. А вот компилятор (оптимизатор) вполне.
по ссылке пример для языка С++, но, на самом деле, проблема может возникнуть для любого языка.
https://habrahabr.ru/post/307702/
Ах, да... именно во избежание подобных бяк и не люблю использовать беззнаковые типы, хотя иногда и можно было бы.
по ссылке пример для языка С++, но, на самом деле, проблема может возникнуть для любого языка.
https://habrahabr.ru/post/307702/
Ах, да... именно во избежание подобных бяк и не люблю использовать беззнаковые типы, хотя иногда и можно было бы.
CRobin писал(а):Дож писал(а):А что, по-вашему, должно являться результатом вычитания этих чисел в UInt64?
должно получится -2 и ранее получалось
UInt64 расшифровывается как Unsigned (беззнаковый) Integer на 64 бита. Как и полагается беззнаковому типу, он не может хранить отрицательные числа
Код: Выделить всё
begin
Writeln('UInt64 of -2 = ', UInt64(-2));
end.
Код: Выделить всё
UInt64 of -2 = 18446744073709551614
Т.е. сейчас указанная вами проблема про вычитание не является ошибкой, а если ранее вы наблюдали -2 в UInt64, то это было что-то странное.
- Лекс Айрин
- долгожитель
- Сообщения: 5723
- Зарегистрирован: 19.02.2013 16:54:51
- Откуда: Волгоград
- Контактная информация:
Дож писал(а): то это было что-то странное.
всего лишь приведение типа, ничего странного. Не думаю, что он присваивал результат в беззнаковую переменную. Другое дело, что этоо детали реализации, которые не всегда явно прописаны.
Лекс Айрин и где это приведение типов? Я что-то не вижу никакого кода.
Дож писал(а):сейчас указанная вами проблема про вычитание не является ошибкой, а если ранее вы наблюдали -2 в UInt64, то это было что-то странное.
Паскаль допускает относительно свободное обращение с типами, например складывать и челочисленные и дробные типы. В моем случае операция вычитания беззнаковых типов применялась в условии
Код: Выделить всё
if a - b > c then Код: Выделить всё
if int64(a - b) > c then - Лекс Айрин
- долгожитель
- Сообщения: 5723
- Зарегистрирован: 19.02.2013 16:54:51
- Откуда: Волгоград
- Контактная информация:
Дож, в паскале много неявного приведения, которое в код добавляет компилятор.
CRobin, всякое бывает. Иногда и не знаешь где аукнется.
CRobin, всякое бывает. Иногда и не знаешь где аукнется.
Вообще-то операция "if a - b > c then" с беззнаковыми типами, если "b" больше "a" является грубой логической ошибкой программиста, а не компилятора. Раньше, когда по молодости делал такие же ошибки в Borland Pascal или Delphi, то при выполнении программа вылетала с ошибкой типа, по-моему, "Run time Error 201 ...".
Когда начал работать в области промышленной автоматизации, то за такие косяки могли уволить с работы или лишить премии на полгода вперед. А если кто-то пытался оправдаться, говоря, что при отключенных проверках диапазонов программа работает правильно, то увольняли сразу и без дальнейших разговоров.
Когда начал работать в области промышленной автоматизации, то за такие косяки могли уволить с работы или лишить премии на полгода вперед. А если кто-то пытался оправдаться, говоря, что при отключенных проверках диапазонов программа работает правильно, то увольняли сразу и без дальнейших разговоров.
alexey38
Давайие сразу сажать за такое))
Обычная ошибка, не лучше не хуже других.
Мерилом в подобных случаях у разрабов является делфи. Раньше было както посвоему, теперь стало как в делфи.
Сейчас (в транке fpc) например такой код работает поразному в делфи\фпц
Напишет ктонить багрепорт и CRobin еще раз удивится))
>>Вообще говоря, меня пугает не то что надо приводить тип, а непредсказукемость алгоритма
Алгоритм тут совершенно непричем,
Давайие сразу сажать за такое))
Обычная ошибка, не лучше не хуже других.
Мерилом в подобных случаях у разрабов является делфи. Раньше было както посвоему, теперь стало как в делфи.
Сейчас (в транке fpc) например такой код работает поразному в делфи\фпц
Код: Выделить всё
program Project1;
{$APPTYPE CONSOLE}
var
a,b:longword;
begin
a:=1;b:=2;
if (a-b)>0 then
Writeln('Passed');
readln;
end.Напишет ктонить багрепорт и CRobin еще раз удивится))
>>Вообще говоря, меня пугает не то что надо приводить тип, а непредсказукемость алгоритма
Алгоритм тут совершенно непричем,
zub писал(а):alexey38Давайие сразу сажать за такое)). Обычная ошибка, не лучше не хуже других.
...
>>Вообще говоря, меня пугает не то что надо приводить тип, а непредсказукемость алгоритма
Алгоритм тут совершенно непричем,
В промышленной автоматизации, если в результате ошибки приведшей к аварии на производстве погибнут люди, то и реально посадят, если не исполнителя, так руководителя проекта. А если ошибка привела к технологическому простою, то могут вкатить и штрафные санкции, в результате чего многолетняя работа окажется за свой счет, при этом обязательства перед заказчиком не снимаются.
В лучшем случае ошибки приводят к дополнительным командировкам, как на разбор сбоя, так и на последующее устранение с переналадкой и испытаниями. Убыток от такой ошибки может легко составить, например, 200 т.р. (на обозначенные дополнительные расходы, если объект удаленный).
Поэтому в промышленной автоматизации очень строго с ошибками, особенно с такими, которые трудно выявляются при тестировании.
Поэтому алгоритм программы должен быть составлен таким образом, чтобы были полностью исключены неопределенности компиляторов и т.п.
