Как сделать из отрицательного числа положительное в c

Добавил пользователь Дмитрий К.
Обновлено: 05.10.2024

Где убираем минус-значение , то есть 5 - (-5) , мы вычисляем это как 10, что да, математически это правильно.

Но в этом случае наша логика должна рассматривать каждое число как положительное, а не отрицательное. Это должно быть 5 - (-5) = 0 в соответствии с нашим требованием.

3 ответа

Вы можете преобразовать отрицательное число в положительное вот так: int myInt = System.Math.Abs(-5); Существует ли эквивалентный метод, чтобы сделать положительное число отрицательным?

Мы все знаем, что старший бит Int32 определяет его знак. 1 указывает, что он отрицательный, а 0 -что он положительный (возможно, обратный). Могу ли я преобразовать отрицательное число в положительное, изменив его старший бит? Я попытался сделать это, используя следующий код: i |= Int32.MaxValue;.

Другие люди предоставили Math.Abs в качестве решения. Я не знаю, есть ли это в строках Math.Abs или нет. Но измерьте прирост производительности от чего-то подобного по сравнению с Math.Abs:

чтобы убедиться, что это действительно того стоит.

EDIT: Я провел несколько быстрых тестов по различным методам, которые вы можете использовать:

Вам нужно использовать Math.Abs()

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

Попробуйте Math.Abs это решит проблему.

Поэтому перед применением какой-либо арифметической операции вы должны применить Math.Abs(value), который преобразует ваше отрицательное значение в положительное.

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

def negate_amount amount = model.amount.to_s (- + amount).to_i end есть ли лучший способ превратить положительное целое число в отрицательное? Приведенный выше код работает, но есть ли для этого.

Как преобразовать отрицательное число в положительное число в шаблоне django? > Если balance.amount-отрицательное число,я хочу.

Как преобразовать положительное целое число в отрицательное с помощью Delphi? Я знаю, что вы можете использовать ABS(int) для преобразования отрицательного в положительное, но мне это нужно, чтобы.

Вы можете преобразовать отрицательное число в положительное вот так: int myInt = System.Math.Abs(-5); Существует ли эквивалентный метод, чтобы сделать положительное число отрицательным?

Мы все знаем, что старший бит Int32 определяет его знак. 1 указывает, что он отрицательный, а 0 -что он положительный (возможно, обратный). Могу ли я преобразовать отрицательное число в.

Как я могу преобразовать отрицательное число в положительное в Python? (И сохраняйте позитивный настрой.)

У меня есть следующий запрос, который я использовал в процедуре и хочу преобразовать одно число в положительное, так как сейчас оно отрицательное. UPDATE SHIPMENT SET TOTAL_SHIP_UNIT_COUNT = ( CASE.

Я пытаюсь преобразовать отрицательное длинное число (например,- 1065576264718330231L) в двоичное. Во-первых, я преобразую отрицательное число в положительное, удаляя знак; Во-вторых, я получаю.

Я хочу отобразить число как отрицательное, используя знак минус: 5000 --> - 5000



В основу статьи легли мои собственные выработанные нелегким путем знания о принципах работы и правильном использовании целых чисел в C/C++. Помимо самих правил, я решил привести список распространенных заблуждений и сделать небольшое сравнение системы целочисленных типов в нескольких передовых языках. Все изложение строилось вокруг баланса между краткостью и полноценностью, чтобы не усложнять восприятие и при этом отчетливо передать важные детали.

Всякий раз, когда я читаю или пишу код на C/C++, мне приходится вспоминать и применять эти правила в тех или иных ситуациях, например при выборе подходящего типа для локальной переменной/элемента массива/поля структуры, при преобразовании типов, а также в любых арифметических операциях или сравнениях. Обратите внимание, что типы чисел с плавающей запятой мы затрагивать не будем, так как это большей частью относится к анализу и обработке ошибок аппроксимации, вызванных округлением. В противоположность этому, математика целых чисел лежит в основе как программирования, так и компьютерной науки в целом, и в теории вычисления здесь всегда точны (не считая проблем реализации вроде переполнения).

Типы данных

Базовые целочисленные типы

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

Несмотря на то, что битовая ширина каждого базового целочисленного типа определяется реализацией (т.е. зависит от компилятора и платформы), стандартом закреплены следующие их свойства:

  • char : минимум 8 бит в ширину;
  • short : минимум 16 бит и при этом не меньше char ;
  • int : минимум 16 бит и при этом не меньше short ;
  • long : минимум 32 бит и при этом не меньше int ;
  • long long : минимум 64 бит и при этом не меньше long .

Наличие знака

  • Стандартный сhar может иметь знак или быть беззнаковым, что зависит от реализации.
  • Стандартные short , int , long и long long идут со знаком. Беззнаковыми их можно сделать, добавив ключевое слово unsigned .
  • Числа со знаком можно кодировать в двоичном формате в виде дополнительного кода, обратного или как величину со знаком. Это определяется реализацией. Заметьте, что обратный код и величина со знаком имеют различные шаблоны битов для отрицательного нуля и положительного, в то время как дополнительный код имеет уникальный нуль.
  • Символьные литералы (в одинарных кавычках) имеют тип ( signed ) int в C, но ( signed или unsigned ) char в C++.

Дополнительные правила

  • sizeof(char) всегда равен 1, независимо от битовой ширины char .
  • Битовая ширина не обязательно должна отличаться. Например, допустимо использовать char , short и int , каждый шириной в 32 бита.
  • Битовая ширина должна быть кратна 2. Например, int может иметь ширину 36 бит.
  • Есть разные способы написания целочисленного типа. К примеру, в каждой следующей строке перечислен набор синонимов:
    • int , signed , signed int , int signed ;
    • short , short int , short signed , short signed int ;
    • unsigned long long , long unsigned int long , int long long unsigned .

    Типы из стандартных библиотек

    • size_t (определен в stddef.h) является беззнаковым и содержит не менее 16 бит. При этом не гарантируется, что его ширина будет как минимум равна int .
    • ptrdiff_t (определен в stddef.h) является целочисленным типом со знаком. Вычитание двух указателей будет давать этот тип. При этом не стоит ожидать, что вычитание двух указателей даст int .
    • В stdint.h определена конкретная ширина типов: uint8_t , int8_t , 16 , 32 и 64 . Будьте внимательны к операциям, подразумевающим продвижение типов. Например, uint8_t + uint8_t даст int (со знаком и шириной не менее 16 бит), а не uint8_t , как можно было предположить.

    Преобразования

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

    Как происходит преобразование?

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

    • Когда исходный тип расширяется до целевого типа с аналогичной знаковой характеристикой (например, signed char -> int или unsigned short -> unsigned long ), каждое исходное значение после преобразования сохраняется.
    • Даже если исходный и целевой типы имеют разные диапазоны, все значения в их пересекающейся части будут сохранены. Например, int , содержащий значение в диапазоне [0, 255] , будет без потерь преобразован в unsigned char .
    • При преобразовании в беззнаковый тип новое значение равняется старому значению по модулю 2 целевая ширина в битах . Объяснение:
      • Если исходный тип беззнаковый и шире целевого, тогда старшие биты отбрасываются.
      • Если исходный тип имеет знак, тогда в процессе преобразования берется исходное значение, и из него/к нему вычитается/прибавляется 2 целевая ширина в битах до тех пор, пока новое значение не впишется в диапазон целевого типа. Более того, если число со знаком представлено в дополнительном коде, то в процессе преобразования старшие биты отбрасываются, как и в случае с беззнаковыми числами.
      • Если исходное значение вписывается в диапазон целевого типа, тогда процесс преобразования (например, расширение знака) производит целевое значение, семантически равное исходному.
      • Если же оно не вписывается, тогда поведение будет определяться реализацией и может вызвать исключение (к примеру, прерывание из-за переполнения).

      Арифметика

      Продвижение/преобразование

      • Унарный арифметический оператор применяется только к одному операнду. Примеры: - , ~ .
      • Бинарный оператор применяется к двум операндам. Примеры: + , * , & . .
      • Если операнд имеет тип bool , char или short (как signed , так и unsigned ), тогда он продвигается до int ( signed ), если int может содержать все значения исходного типа. В противном случае он продвигается до unsigned int . Процесс продвижения происходит без потерь. Примеры:
        • В реализации присутствуют 16-битный short и 24-битный int . Если переменные x и y имеют тип unsigned short , то операция x & y продвигает оба операнда до signed int .
        • В реализации присутствуют 32-битный char и 32-битный int . Если переменные x и y имеют тип unsigned char , то операция x – y продвигает оба операнда до unsigned int .
        • (long) + (long) → (long) ;
        • (unsigned int) * (int) → (unsigned int) ;
        • (unsigned long) / (int) → (unsigned long) ;
        • если int является 32-битным, а long 64-битным: (unsigned int) % (long) → (long) ;
        • если int и long оба являются 32-битными: (unsigned int) % (long) → (unsigned long) .

        Неопределенное поведение

        Знаковое переполнение:

        • При выполнении арифметических операций над целочисленным типом переполнение считается неопределенным поведением (UB). Такое поведение может вызывать верные, несогласованные и/или неверные действия как сразу, так и в дальнейшем.
        • При выполнении арифметики над беззнаковым целым (после продвижений и преобразований) любое переполнение гарантированно вызовет оборот значения. Например, UINT_MAX + 1 == 0 .
        • Выполнение арифметики над беззнаковыми целыми фиксированного размера может привести к едва уловимым ошибкам. Например:
          • Пусть uint16_t = unsigned short , и int равен 32-битам. Тогда uint16_t x=0xFFFF , y=0xFFFF , z=x*y ; x и y будут продвинуты до int , и x * y приведет к переполнению int , вызвав неопределенное поведение.
          • Пусть uint32_t = unsigned char , и int равен 33-битам. Тогда uint32_t x=0xFFFFFFFF , y=0xFFFFFFFF , z=x+y ; x и y будут продвинуты до int , и x + y приведет к переполнению int , то есть неопределенному поведению.
          • Чтобы обеспечить безопасную арифметику с беззнаковыми целыми, нужно либо прибавить 0U , либо умножить на 1U в качестве пустой операции. Например: 0U + x + y или 1U * x * y . Это гарантирует, что операнды будут продвинуты как минимум до ранга int и при этом останутся без знаков.
          • Деление на нуль и остаток с делителем нуля также относятся к неопределенному поведению.
          • Беззнаковое деление/остаток не имеют других особых случаев.
          • Деление со знаком может вызывать переполнение, например INT_MIN / -1 .
          • Остаток со знаком при отрицательных операндах может вызывать сложности, так как некоторые части являются однообразными, в то время как другие определяются реализацией.
          • Неопределенным поведением считается битовый сдвиг ( >) на размер, который либо отрицателен, либо равен или больше битовой ширины.
          • Левый сдвиг беззнакового операнда (после продвижения/преобразования) считается определенным правильно и отклонений в поведении не вызывает.
          • Левый сдвиг операнда со знаком, содержащего неотрицательное значение, вследствие которого 1 бит переходит в знаковый бит, является неопределенным поведением.
          • Левый сдвиг отрицательного значения относится к неопределенному поведению.
          • Правый сдвиг неотрицательного значения (в типе операнда без знака или со знаком) считается определенным правильно и отклонений в поведении не вызывает.
          • Правый сдвиг отрицательного значения определяется реализацией.

          Счетчик цикла

          Выбор типа

          Предположим, что у нас есть массив, в котором нужно обработать каждый элемент последовательно. Длина массива хранится в переменной len типа T0 . Как нужно объявить переменную счетчика цикла i типа T1 ?

          • Самым простым решением будет использовать тот же тип, что и у переменной длины. Например:
          • Говоря обобщенно, переменная счетчика типа T1 будет работать верно, если диапазон T1 будет являться (не строго) надмножетсвом диапазона T0 . Например, если len имеет тип uint16_t , тогда отсчет с использованием signed long (не менее 32 бит) сработает.
          • Говоря же более конкретно, счетчик цикла должен просто покрывать всю фактическую длину. Например, если len типа int гарантированно будет иметь значение в диапазоне [3,50] (обусловленное логикой приложения), тогда допустимо отсчитывать цикл, используя char без знака или со знаком (в котором однозначно можно представить диапазон [0,127] ).
          • Нежелательно использовать переменную длины и переменную счетчика с разной знаковостью. В этом случае сравнение вызовет неявное сложное преобразование, сопровождаемое характерными для платформы проблемами. К примеру, не стоит писать такой код:

          Отсчет вниз

          Для циклов, ведущих отсчет вниз, более естественным будет использовать счетчик со знаком, потому что тогда можно написать:


          При этом для беззнакового счетчика код будет таким:


          Примечание: сравнение i >= 0 имеет смысл только, когда i является числом со знаком, но всегда будет давать true , если оно будет беззнаковым. Поэтому, когда это выражение встречается в беззнаковом контексте, значит, автор кода скорее всего допустил ошибку в логике.

          Заблуждения

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

          Есть задание - найти X чисел из последовательности Фибоначчи. По непонятной мне причине, после этого места:


          Тип данных возьми пошире.

          У меня везде int. Предлагаешь взять double?

          int это вроде от -2 миллиардов до +2 двух миллиардов. Когда переваливаешь за max_int, из числа вычиается 2^32 и оно превращается в отрицательное.

          Если тебя устроит округление. Вообще есть long и long long.


          double для чисел с плавающей точкой.

          Используй unsigned long или unsigned long long.


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

          Тот, который я читал, говорит лишь о string, int, double, char. Во всяком случае, в первых нескольких главах.

          Числа положительные стали перемежаться числами отрицательными.

          переполнение. самый старший бит в знаковом инте, например, отвечает за знак.

          Взял long long. Отрицательности больше нет, но все равно немного чудит:


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

          Сомневаюсь, что кого-либо волнует 100-200 число последовательности, но ощущение неприятное.


          Код показывай тогда


          Тоже самое. Нужно использовать какую-нибудь библиотечку для математики (это не ко мне).

          Ты хотел любые бесконечно большие числа int'ом или double'ом хранить? Напиши длинную арифметику для начала.

          Мне немного стыдно. Боюсь, сочтете быдлокодом. В любом случае:

          Еще не разобрался с проблемой, которая проявляется в том, что какого-то черта вычисление и вывод не останавливается, когда переменная amounts становится равна переменной amount (amount считывается в начале, а amounts равна 0 и увеличивается на один каждый раз. Но я разберусь.


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

          while на do<>while поменяй. Он условие проверяет в конце цикла.


          Ты в цикле инкрементируешь трижды amounts и иногда пролетаешь amount.

          Мне немного стыдно. Боюсь, сочтете быдлокодом.

          Сочтем. Самый обычный быдлокод.

          какого-то черта вычисление и вывод не останавливается, когда переменная amounts становится равна переменной amount

          Hint: У тебя amounts на каждой итерации цикла while увеличивается на 3, а не на 1.


          На unsigned long long ты доедешь только до 84-го числа.

          amount = 2 amounts = 0

          первый шаг цикла

          amounts++(1) amounts++(2) amounts++(3)

          второй шаг цикла

          Понял, в чем проблема. Буду размышлять.

          Ладно, раз без мук дальше никак - забью.

          Да какие муки?:) Возьми GMP(как выше уже два раза советовали), и напиши точно такую же программу. Туториалов по GMP полно в сети, в программе по-сути ничего не изменится кроме типа данных.

          GMP - general multiprecision library


          Интересно, а можно формулой реализовать?

          Там же есть, с золотым сечением

          Вставил проверку условия каждый раз и цикл реализовал через while(1). Работает, как надо.

          Можно рекурсивно замутить, попробовать Хотя стек может подвести и кончиться:)

          Некрасиво же. И вообще, у тебя три одинаковых вычисления идёт. Лучше переделать. Например через рекурсию, или через определители, или через золотое сечение(формула Бине)

          На этом уроке мы рассмотрим арифметические операторы и их использование в языке С++.

          Унарные арифметические операторы

          Унарные операторы — это операторы, которые применяются только к одному операнду. Существуют два унарных арифметических оператора: плюс ( + ) и минус ( − ).

          Оператор Символ Пример Операция
          Унарный плюс + +x Значение x
          Унарный минус −x Отрицательное значение x

          Унарный оператор + возвращает значение операнда. Другими словами, +5 = 5 или +х = х . Унарный плюс вам, скорее всего, не придется использовать. Его по большей части добавили в качестве симметрии с унарным оператором минус. Унарный оператор минус возвращает операнд, умноженный на −1 . Например, если х = 5 , то −х = −5 .

          Оба этих оператора пишутся непосредственно перед самим операндом, без пробела ( −x , а не − x ).

          Не следует путать унарный оператор минус с бинарным оператором вычитания, хоть они и используют один и тот же символ. Например, в выражении х = 5 − −3; , первый минус — это оператор вычитания, а второй — унарный минус.

          Бинарные арифметические операторы

          Бинарные операторы — это операторы, которые применяются к двум операндам (слева и справа). Существует 5 бинарных операторов.

          Оператор Символ Пример Операция
          Сложение + x + y x плюс y
          Вычитание x − y x минус y
          Умножение * x * y x умножить на y
          Деление / x / y x разделить на y
          Деление с остатком % x % y Остаток от деления x на y

          Операторы сложения, вычитания и умножения работают так же, как и в обычной математике. А вот деление и деление с остатком рассмотрим детально.

          Деление целых чисел и чисел типа с плавающей точкой

          Оператор деления имеет два режима. Если оба операнда являются целыми числами, то оператор выполняет целочисленное деление. Т.е. любая дробь (больше/меньше) отбрасывается и возвращается целое значение без остатка, например, 7 / 4 = 1 .

          Если один или оба операнда типа с плавающей точкой, то тогда будет выполняться деление типа с плавающей точкой. Здесь уже дробь присутствует. Например, выражения 7.0 / 3 = 2.333 , 7 / 3.0 = 2.333 или 7.0 / 3.0 = 2.333 имеют один и тот же результат.

          Попытки деления на 0 (или на 0.0 ) станут причиной сбоя в вашей программе, и это правило не следует забывать!

          Использование оператора static_cast в операциях деления

          На уроке о символьном типе данных char мы уже использовали оператор static_cast для вывода ASCII-символов в виде целых чисел.

          Аналогичным образом мы можем использовать static_cast для конвертации целого числа в число типа с плавающей точкой. Таким образом, вместо целочисленного деления выполнится деление типа с плавающей точкой. Например:

          std :: cout "double / double crayon-h"> static_cast double > ( x ) / static_cast double > ( y ) "\n" ;

          Результат выполнения программы:

          int / int = 1
          double / int = 1.75
          int / double = 1.75
          double / double = 1.75

          Деление с остатком

          Оператор деления с остатком ( % ) работает только с целочисленными операндами и возвращает остаток от целочисленного деления. Например:

          Пример №1: 7 / 4 = 1 с остатком 3 , таким образом, 7 % 4 = 3 .

          Пример №2: 25 / 7 = 3 с остатком 4 , таким образом, 25 % 7 = 4 . Остаток составляет не дробь, а целое число.

          Пример №3: 36 % 5 = 7 с остатком 1 . В числе 36 только 35 делится на 5 без остатка, поэтому 36 − 35 = 1 , 1 — это остаток и результат.

          Данный оператор чаще всего используют для проверки деления без остатка одних чисел на другие. Если х % у == 0 , то х делится на у без остатка.

          Например, мы хотим написать программу, которая выводит числа от 1 до 100 по 20 значений в каждой строке. Мы можем использовать оператор деления с остатком для создания разрыва строк. Несмотря на то, что мы еще не рассматривали цикл while, в следующей программе всё максимально просто и понятно:

          Результат выполнения программы:

          1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
          21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
          41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
          61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
          81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

          О while мы еще поговорим на соответствующем уроке.

          Отрицательные числа в операциях деления до C++11

          До C++11, если любой из операндов целочисленного деления является отрицательным, то компилятор округляет результат самостоятельно! Например, результатом −5 / 2 может быть либо −3 , либо −2 . Однако большинство современных компиляторов округляют числа в сторону нуля (например, в −5 / 2 результатом будет −2 ). В спецификации C++11 определили, что компилятор должен всегда округлять к нулю (или, проще говоря, просто отбрасывать дробь).

          Также до C++11, если один из операндов оператора деления с остатком является отрицательным, то результат может быть как положительным, так и отрицательным! Например, результатом −5 % 2 может быть как 1 , так и −1 . В спецификации C++11 решили сделать так, чтобы результат a % b был того же знака, что и значение а .

          Арифметические операторы присваивания

          Оператор Символ Пример Операция
          Присваивание = x = y Присваиваем значение y переменной x
          Сложение с присваиванием += x += y Добавляем y к x
          Вычитание с присваиванием −= x −= y Вычитаем y из x
          Умножение с присваиванием *= x *= y Умножаем x на y
          Деление с присваиванием /= x /= y Делим x на y
          Деление с остатком и с присваиванием %= x %= y Присваиваем остаток от деления x на y переменной x

          До этого момента, когда нам нужно было добавить число 5 к определенной переменной, мы делали следующее:

          Читайте также: