Как сделать из отрицательного числа положительное в c
Где убираем минус-значение , то есть 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 к определенной переменной, мы делали следующее:
Читайте также: