Вычтите беззнаковые целые числа в длинный результат со знаком. Никогда не отрицательный?

Обнаружил ошибку в своем коде и заметил следующее при вычитании двух чисел, например

unsigned int a, b (при b > a)

длинный результат со знаком = a - b

Результат всегда положительный, даже если b больше. Я ожидал, что, поскольку результат подписан, результат тоже будет преобразован в подписанный, но, видимо, нет. Как я могу это исправить?

Итак, вы тоже ожидаете, что double frac = 3 / 5; даст вам 0,6?

sweenish 04.04.2024 19:23

@sweenish Многие новички ожидают именно этого. А вот про ОП ничего не могу сказать.

john 04.04.2024 19:27

@john Хотя я знаю, это также было описано в моей второй лекции. Не говорю, что ОП — мой ученик, но обычно это одна из первых ошибок, о которой кто-либо узнает.

sweenish 04.04.2024 19:29

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

dac1n 04.04.2024 20:13

Также обновите, я использовал (подписано) (a-b)... и все работает. То есть это похоже на выполнение (double)(a/b) и получение результата в десятичном виде? для меня не имеет смысла, почему это работает сейчас

dac1n 04.04.2024 20:16

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

user4581301 04.04.2024 20:56
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
106
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема в том, что ваши математические действия выполняются — с unsigned ints, в результате чего получается unsigned int — до того, как значение преобразуется в long. Когда беззнаковый тип преобразуется в более крупный знаковый тип, значение не меняется. Таким образом, ваш результат может быть отрицательным только в том случае, если long и int имеют одинаковый размер.

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

С оговоркой, что присвоение значения, выходящего за пределы диапазона, целому числу со знаком по-прежнему является UB.

user4581301 04.04.2024 19:31

ИБ, судя по всему. По крайней мере, до C++20. Но математика все равно может открыть червоточину, если long и int имеют одинаковый размер.

cHao 04.04.2024 19:33

Джа. Я неправильно запомнил. Это переполнение, а не присвоение слишком большого значения, то есть и остаётся UB.

user4581301 04.04.2024 19:59

Вы уверены, что это правильно? Я добавил (подписанный) (ab), который нашел в Интернете, и теперь он работает. Почему приведение к подписанному типу дает правильный результат, а неявное приведение к подписанному типу — нет?

dac1n 04.04.2024 20:11

@dac1n: По сути, потому что (signed)(a-b) преобразуется в тип, слишком маленький для хранения всех значений unsigned, поэтому он преобразует беззнаковое в знаковое, как указывает компилятор (особенно распространенным поведением является переинтерпретация как дополнение до двух). Но я предполагаю, что вы хотели long, потому что, например, (signed)(0-UINT_MAX) не дает вам той ценности, которую вы ожидаете.

cHao 04.04.2024 20:35

Хорошо, спасибо, это был просто крайний случай. Подводя итог, при выполнении таких операций результатом является «более высокий» тип из двух или тип любого из них, если он одинаковый, независимо от того, какой тип переменной результата вы ей назначаете?

dac1n 04.04.2024 21:05

@dac1n: Очень похоже. См. en.cppreference.com/w/cpp/language/usual_arithmetic_conversi‌​ons (в вашем случае обратите особое внимание на этап 5).

cHao 04.04.2024 23:13

Другие вопросы по теме

Похожие вопросы

Назначаемая функция в C++
Выражение: индекс вектора выходит за пределы допустимого диапазона для системы повышения ранжирования
Перегрузка операторов с помощью дженериков, несколько абстрактных классов С++
Что такое noptr-declarator в объявлении массива C++?
Создание собственного всплывающего окна, которое меняет высоту в зависимости от содержимого и при необходимости добавляет полосу прокрутки
Как создать абстрактный класс внутри родительского класса, чтобы каждый дочерний класс мог иметь собственную реализацию?
Есть ли вероятность того, что упрощенные формы определенных математических выражений вызовут ошибки переполнения, а сложные — нет?
Как написать функцию C++, которая удаляет указатель вместо макроса
Как нарисовать наложение в C++?
Как обобщить специализацию шаблона для любого типа шаблона с переменным числом вариантов?