Там нет реальной необходимости решения этого, я просто хочу знать, почему.
Давайте возьмем два числа:
#include <iostream>
using namespace std;
int main()
{
unsigned long long int a = 17446744073709551615;
signed long long int b = -30000000003;
signed int c;
c = a/b;
cout << "\n\n\n" << c << endl;
}
Теперь в последнее время я получаю нулевой ответ. Размер моего длинного длинного составляет 8 байтов, так что более чем достаточно, чтобы взять его с беззнаковой меткой. Переменная C также должна быть достаточно большой, чтобы обрабатывать ответ. (Это должно быть -581 558 136, согласно Google). Так…
Изменить Я хотел бы отметить, что на моей машине …
Использование numeric_limits a хорошо ложится в пределах максимума 18446744073709551615, а b попадает в минимальные пределы -9223372036854775808.
У вас происходит ряд неявных преобразований, большинство из которых не нужны.
unsigned long long int a = 17446744073709551615;
Десятичный целочисленный литерал без суффикса имеет тип int
, long int
, или же long long int
; это никогда не беззнаковый тип. Это конкретное значение почти наверняка превышает максимальное значение long long int
(263-1). Если ваш компилятор не имеет целочисленный тип со знаком шире 64 бит, это делает вашу программу плохо сформированной.
Добавить ULL
суффикс, чтобы гарантировать, что литерал имеет правильный тип:
unsigned long long int a = 17446744073709551615ULL;
Значение оказывается между 263-1 и 264-1, поэтому он подходит для 64-разрядного типа без знака, но не для 64-разрядного типа со знаком.
(На самом деле только U
было бы достаточно, но это не мешает быть явным.)
signed long long int b = -30000000003;
Это не должно быть проблемой. 30000000003
имеет некоторый целочисленный тип со знаком; если ваш компилятор поддерживает long long
шириной не менее 64 бит, переполнения нет. Тем не менее, пока вам нужен суффикс на значении a
, не мешало бы быть явным:
signed long long int b = -30000000003LL;
Теперь у нас есть:
signed int c;
c = a/b;
Разделение unsigned long long
по signed long long
вызывает преобразование подписанного операнда в unsigned long long
, В этом случае конвертируемое значение является отрицательным, поэтому оно преобразуется в большое положительное значение. преобразование -30000000003
в unsigned long long
доходность 18446744043709551613
, Разделив 17446744073709551615
от 18446744043709551613
дает ноль.
Если ваш компилятор не поддерживает целые числа шире 64 бит (большинство не поддерживает), вы не сможете непосредственно делить 17446744073709551615
от -30000000003
и получите математически правильный ответ, поскольку нет целочисленного типа, который может представлять оба значения. Все арифметические операторы (кроме операторов сдвига) требуют операнды одного типа с неявными преобразованиями, применяемыми по мере необходимости.
В этом конкретном случае вы можете разделить 17446744073709551615ULL
от 30000000003ULL
а затем учитывать знак. (Проверьте правила языка для деления отрицательных целых чисел.)
Если вам действительно нужно сделать это в целом, вы можете прибегнуть к плавающей запятой (что означает, что вы, вероятно, потеряете некоторую точность) или использовать какой-либо целочисленный арифметический пакет произвольной ширины, например GMP.
b рассматривается как число без знака, которое больше, чем a. Следовательно, вы получаете ответ как 0.
Попробуйте использовать это как
c = abs(a) / abs (b)
if ((a < 0 && b > 0 ) || (a> 0 && b < 0))
return -c;
return c;