LINUX.ORG.RU

Ответ на: комментарий от anonymous

А чем тебе типы помогут? Длина слова всё ещё конечная и ты либо возвращаешь результат как значение двойной длины, либо обрабатываешь переполнение, либо говоришь что «у нас тут дополнение до двойки и всё».

Dark_SavanT ★★★★★
()
Ответ на: комментарий от next_time

Не всегда, но если не влезает в фиксед тип, то используются биг типы. Но если влезло, то норм.

turtle_bazon ★★★★★
()
Ответ на: комментарий от next_time

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

turtle_bazon ★★★★★
()
Ответ на: комментарий от Dark_SavanT

В мейнстрим ЯП не помогут. Но ничто не мешает использовать более богатую систему типов для выявления переполнения на этапе компиляции.

anonymous
()
Ответ на: комментарий от next_time

каков будет результат и какое он имеет отношение к искомой площади прямоугольника?

Есть теорема в дискретной математике о том, что при перемножении чисел размером N разрядов размер результата будет 2*N разрядов. А теперь вспомни как числа вообще представляются в памяти ЭВМ.

Так что ответ таков: используя «длинную арифметику» ты избежишь подобных ситуаций. Иначе никак.

LongLiveUbuntu ★★★★★
()

Мой любимый язык программирования — это ассемблер КР580ВМ80А. При переполнении выставляется соответствующий флаг в регистре флагов.

Infra_HDC ★★★★★
()
Ответ на: комментарий от next_time

Т.е. для сложения любых данных, неизвестных на этапе компиляции компиляции - ошибка компиляции?

trex6 ★★★★★
()

В c++ нет ничего. По сути, единственный рабочий вариант умножения это скастовать один из множителей к long long.

Его и используют.

d_a ★★★★★
()
Ответ на: комментарий от red75prim

Я даже решил вернуться и проверить либу. Может ли она в нормальную крестовую логику. И оказалось может: https://godbolt.org/z/qxodcg

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

А ещё можно реализовать константы и можно будет написать цикл на миллиард с умножением на ноль. Там возможно даже есть поддержка этого. Но что-то я так сразу не нашел.

Ну это без проблем приколхозить даже если нету поддержки через реализацию numeric_limits для констант.

anonymous
()
Ответ на: комментарий от next_time

интересно, есть хоть один язык, в котором переполнение при умножение приводит к ошибке компиляции

 
// запросы к БД LORа, рантайм значения
let overall = get_amount_of_comments("next_time");
let tcoef = get_tupnyak_coefficient("next_time");

// вот тут будет переполнение, как защищаться в компилтайме?
let tamount = overall * tcoef;
mersinvald ★★★★★
()
Последнее исправление: mersinvald (всего исправлений: 1)

Например, при перемножении двух переменных?

Red 0.6.4:

>> >> a: 3278934032849022348732897498327323248902859028490582490859042890589204348590234849058240935802438504832837
== 3.278934032849023e105
>> a * a * a
== 1.#INF

NodeJS 12.4.0:

> a = 3278934032849022348732897498327323248902859028490582490859042890589204348590234849058240935802438504832837
3.2789340328490225e+105
> a * a * a
Infinity
rebforce
()
Ответ на: комментарий от mersinvald

// вот тут будет переполнение, как защищаться в компилтайме?

Ну если тут возможно переполнение - это можно обнаружить. Примеры выше даны. А далее уже думай.

anonymous
()
Ответ на: комментарий от mersinvald

Оценить можно и в компилтайме.

anonymous
()
Ответ на: комментарий от rebforce

Во втором примере результат к double приводится, а с ним все ясно.

LongLiveUbuntu ★★★★★
()
Ответ на: комментарий от mersinvald

Можно (теоретически) ловить и в компайл-тайме. Обсуждали же даже на лоре уже не раз.

uint32_t a, b, c;

a = rand();
b = rand();

if ((a < UINT16_MAX) && (b < UINT16_MAX))
    c = a * b; /* все нормально, здесь не может быть переполнения */
} else {
    c = a * a; /* а здесь переполнение может быть, (очень) умный компилятор мог бы сделать предупреждение */
}

Deleted
()
Ответ на: комментарий от Deleted

TypeScript и вроде Hack делают забавную штуку в этом духе. Если родительский класс обычным «if» проверить на instanceof подкласса, то внутри блока переменная будет считаться уже типа подкласса

vertexua ★★★★★
()

Машина зажимает перфокарту и зажигает красную лампу со звуковым сигналом. После чего её нужно перезапустить.

anonymous
()
Ответ на: комментарий от Deleted

Можно (теоретически) ловить и в компайл-тайме.

Выше уже показано, что оценкой сверху всё ловится без проблем.

а здесь переполнение может быть, (очень) умный компилятор мог бы сделать предупреждение

Это говно бездарное. Подобная схема тебе никак не может. Послал a и b куда-то и сломались твои проверки.

То что было показано выше не сломается.

anonymous
()
Ответ на: комментарий от vertexua

TypeScript и вроде Hack делают забавную штуку в этом духе. Если родительский класс обычным «if» проверить на instanceof подкласса, то внутри блока переменная будет считаться уже типа подкласса

Это примитивная херня, которая в десять раз проще реализуется, чем показанное выше. Нужна только в скриптухе.

anonymous
()
Ответ на: комментарий от red75prim

и constraint propagation развалится.

не волнуйся, у тебя оно развалится и на том хелворде. Какой смысл пытаться что-то критиковать будучи адептов пхп? Тут скорее всего говорит не твоё какое-то маня-чувство объективности, а просто попытка защищать свою бездарную веру.

anonymous
()
Ответ на: комментарий от red75prim

constraint propagation развалится.

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

Мы же пишем об инструменте, который подсказывал бы пользователю о потенциальных ошибках, желательно пораньше, в компайл-тайм.

Вот допустим тут c = c * 3 + 1; мы не можем сделать предположений относительно c, но вполне можем предупредить пользователя о том что возможно переполнение

Deleted
()
Ответ на: комментарий от rebforce

При переполнении ошибки тоже не происходит. Очевидно, что inf это не то, что нужно получить - это уже ошибка, ошибка в полученном результате вычислений.

anonymous
()
Ответ на: комментарий от trex6

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

next_time ★★★★★
() автор топика
Ответ на: комментарий от next_time

Т.е. для всех данных, полученных извне - пользовательского ввода, результатов запросов в БД, ответов серверов?

trex6 ★★★★★
()
Ответ на: комментарий от trex6

Т.е. для всех данных, полученных извне - пользовательского ввода, результатов запросов в БД, ответов серверов?

Да, такой компиль тебе скажет, грубо говоря, что ты забыл проверить. Добавишь нужные проверки и все скомпилится.

Но для данной задачи это жесть.

anonymous
()
Ответ на: комментарий от trex6

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

Т.е. на деле, вы всё подряд в храните в простом int просто в силу лени, а по факту - вы имеете налицо изъян в системе типов. В плюсах можно наклепать шаблонов для работы с числами ограниченной размерности - и тогда компилер будет корректно проверять переполнение на этапе компиляции. Просто это будет чуть менее удобно, чем работа с простым инт.

Вот я и смотрю из любопытства в сторону других ЯП.

next_time ★★★★★
() автор топика
Последнее исправление: next_time (всего исправлений: 1)
Ответ на: комментарий от next_time

Я правильно понял идею: на ходу генерить типы LimitedInt<0,100> у которого значения будут только из этого отрезка? Сложение/умножение/деление для обычных арифметических типов запретить. LimitedInt без конструктора, фабричный метод возвращает Option.

Звучит неплохо. Надо будет попробовать запилить. Вопрос только, как запретить операции для встроенных типов и что делать с кучей библиотек, которые с таким типом данных работать не умеют.

trex6 ★★★★★
()
Последнее исправление: trex6 (всего исправлений: 1)
Ответ на: комментарий от next_time

Т.е. на деле, вы всё подряд в храните в простом int просто в силу лени

Нет, не от лени. Это в принципе невозможно реализовать на рядовых недоязычках. Для реализации есть два варианта - это актуальный С++ и фп-маргинальщина с зависимыми типами типа кока, идриса. Но маргинальная фп-скриптуха в принципе не является состоятельной для прикладных задач. Что бы там адепты идриса не кукарекали.

anonymous
()
Ответ на: комментарий от trex6

Я правильно понял идею: на ходу генерить типы LimitedInt<0,100> у которого значения будут только из этого отрезка?

Эта идея уже показана и реализована выше.

hana::iterate<4>(_ * uint8_t{}, pedantic<int>{})

Т.е. pedantic<int> это значение типа int с диапазоном от min до max.

Далее оно умножается на uint8_t 4 раза. Т.е. диапазон умножается каждую итерацию. Т.е. каждый тип хранит в себе максимальное/минимальное значение которое может быть в него записано.

Сложение/умножение/деление для обычных арифметических типов запретить.

Какая чушь. В чём смысл запрета?

LimitedInt без конструктора, фабричный метод возвращает Option.

Тоже какая-то херня. Причём тут Option?

Звучит неплохо. Надо будет попробовать запилить. Вопрос только, как запретить операции для встроенных типов и что делать с кучей библиотек, которые с таким типом данных работать не умеют.

Ты не сможешь это реализовать - можешь даже не пытаться.

В нормальной языке с этим проблем нет. Там имеет место явное неявное преобразование типов. Выше оно показано. uint8_t воспринимается как любое значение из диапазона uint8_t. ты можешь дописать операцию, которая будет ограничивать значение. Эта операция будет возвращать такой же uint8_t, но его значение будет ограничено условными 0 - 100, а не 0 - 255 как в базовом случае.

Каждая операция увеличивает значение исходя из семантики операции. Так же тебе нужно ввести специальные типы для констант. В нормальном языке это так же без проблем реализуется. 100 -> 100_c.

anonymous
()
Ответ на: комментарий от next_time

интересно, есть хоть один язык, в котором переполнение при умножение приводит к ошибке компиляции, а не тихое проглатывание с экзепшеном (паникой и т.п.) в рантайме?

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

annulen ★★★★★
()

В С++ это просто undefined behavour

Только для знаковых типов. Но и для них есть нестандартные расширения -ftrapv и -fwrapwv

annulen ★★★★★
()
Ответ на: комментарий от anonymous

явное неявное преобразование типов

Смешно.

Причём тут Option?

Передаем в фабричный метод значение, введенное пользователем, если значение удовлетворяет ограничениям - возращаем Some(LimitedInt<BottomLimit, TopLimit>), если нет - None. В итоге программист будет вынужден проверять, попадает ли значение в интервал.

В чём смысл запрета?

Чтобы не переполняли что попало, а работали только через LimitedInt и другие.

Эта идея уже показана и реализована выше.

Времени прочитать весь тред у меня, конечно же, нет.

Ты не сможешь это реализовать - можешь даже не пытаться.

А ты смешной.

trex6 ★★★★★
()
Ответ на: комментарий от annulen

Для этого умножение должно происходить во время компиляции

Можно на этапе копмиляции ограничиться лимитами значений.

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

trex6 ★★★★★
()
Ответ на: комментарий от annulen

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

trex6 ★★★★★
()
Ответ на: комментарий от anonymous

Так на C++ вполне себе можно реализовать.

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

trex6 ★★★★★
()
Ответ на: комментарий от trex6

Я правильно понял идею: на ходу генерить типы LimitedInt<0,100> у которого значения будут только из этого отрезка?

совершенно верно

Вопрос только, как запретить операции для встроенных типов

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

и что делать с кучей библиотек, которые с таким типом данных работать не умеют

на практике, большинства библиотек, кстати, используют числа только для хранения кодов каких-нибудь состояний и размеров - тогда особо и не надо что-то менять

проблема больше актуальна для прикладного кода, а не библиотек

next_time ★★★★★
() автор топика
Ответ на: комментарий от trex6

Смешно.

Слишком слаб. Ну давай «управляемое неявное преобразование типов» - авось попроще будет.

Передаем в фабричный метод значение, введенное пользователем, если значение удовлетворяет ограничениям - возращаем Some(LimitedInt<BottomLimit, TopLimit>), если нет - None. В итоге программист будет вынужден проверять, попадает ли значение в интервал.

Это ничего не даст. Если что-то больше - это так же валидный путь.

Чтобы не переполняли что попало, а работали только через LimitedInt и другие.

Это проблемы твоего восприятия. Они не будут переполнять что попало.

Времени прочитать весь тред у меня, конечно же, нет.

Там выше ссылка на https://godbolt.org/z/qxodcg

А ты смешной.

Ну я подожду, а потом посмеёмся вместе.

anonymous
()
Ответ на: комментарий от trex6

Так на C++ вполне себе можно реализовать.

Только на С++.

Проблемы только в том,

А ещё больше на коках, дальше что? К тому же это неверное. С++ компилируется быстрее любого другого недоязычка. Разница только в том, что кода на С++ попросту больше.

что компиляция будет занимать очень много времени

Нет.

и непонятно как спасаться от переполнения в библиотеках

Это ненужно. Реализовать что-то, что могло-бы работать с этими библиотеками ты итак не сможешь. Толку от этих рассуждений?

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.