Nano Hash - криптовалюты, майнинг, программирование

Целочисленное переполнение с UDL (определяемым пользователем литералом) для __int128 @ min отрицательное значение

Для ясности и простоты я буду сокращать следующие числа следующим образом:

  • −170,141,183,460,469,231,731,687,303,715,884,105,728 as -170…728
  • 170,141,183,460,469,231,731,687,303,715,884,105,727 as 170…727

Эти числа представляют минимальное и максимальное значения 128-битного целого числа со знаком (__int128 в gcc).

Я реализовал определяемые пользователем литералы (необработанные литералы) для этого типа данных, поскольку gcc не предлагает способ определения констант этого типа: _u128 для unsigned __int128 и _i128 для __int128.

Знак минус не является частью UDL, а является унарным минусовым оператором, применяемым к результату UDL.

Таким образом, для -ddddd_i128 (где d — цифра) UDL вычисляет со знаком __int128 с положительным значением ddddd, а затем компилятор применяет к нему унарный оператор минус. Все идет нормально.

Проблема связана с -170…128_i128 (которое должно быть допустимым значением для __int128):
UDL вычисляет со знаком __int128 положительное число 170…128, которое выходит за пределы диапазона __int128, что приводит к Неопределенному поведению ( целочисленное переполнение со знаком).

Любое решение для представления этой числовой константы с помощью UDL?


Объявлены мои UDL (на данный момент просто версия без constexpr, loopy) (это необработанные литералы):

unsigned __int128 operator"" _u128(char const *str);
__int128 operator"" _i128(char const *str);

Некоторые варианты использования:

  1000000000000000000000000000000000_i128
  -1000000000000000000000000000000000_i128
  -170141183460469231731687303715884105728_i128 // <-- this has UB
  170141183460469231731687303715884105727_u128
  340282366920938463463374607431768211455_u128

Я знаю, что существуют способы определения константы -170…728 различными способами, такими как битовые сдвиги, математические операции, но я хочу иметь возможность создавать ее согласованным образом, например. Я не хочу такой ситуации: с помощью этого UDL можно создать любую константу, кроме -170…728_i128, для которой приходится использовать дополнительные приемы.


  • Является ли (__int128)1<<127 UDL? Как насчет ~MAX_INT128, где MAX_INT128 — это UDL, который работает на вас? 05.08.2014
  • Как определяется ваш UDL? Насколько я знаю, вы не можете иметь тип параметра больше, чем unsigned long long. 05.08.2014
  • @Praetorian, ты думаешь о приготовленных литералах. Необработанные литералы дают каждую цифру отдельно в C-строке, поэтому вы не привязаны к типам (например, long long) 05.08.2014
  • @barakmanos (__int128)1‹‹127 не является UDL 05.08.2014
  • См. groups.google.com. /a/isocpp.org/forum/?fromgroups#!topic/ 05.08.2014

Ответы:


1

По сути, это та же проблема, с которой сталкиваются разработчики при реализации <limits.h>: INT_MIN нельзя определить (в типичной 32-разрядной системе) как -2147483648. Вместо этого он может быть (и обычно определяется) как (-2147483647 - 1). Вам придется сделать что-то подобное. Возможно, не существует никакого способа представить самое отрицательное число с помощью одного оператора отрицания и литерала, но это нормально: в этом просто нет необходимости.

05.08.2014
  • так вы говорите, что если я напишу константу -2147483648 (в системе, где int 32 бита), это UB? 05.08.2014
  • @bolov Нет, но 2147483648 будет иметь тип long long, поэтому выражение не имеет предполагаемого значения. FWIW, версия long long (обычно -9223372036854775808) недействительна. Не неопределенное поведение, но если нет целочисленного типа со знаком, который может содержать 9223372036854775808, то использование 9223372036854775808 всегда будет ошибкой. 05.08.2014
  • @bolov: -2147483648 не буквальный. Это выражение, состоящее из литерала 2147483648 с примененным к нему унарным оператором -. Унарный - может переполниться. 05.08.2014
  • Верно. INT_MAX — 2 147 483 647. 06.08.2014
  • Новые материалы

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

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

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

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

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..