Какой тип данных используется для хранения промежуточных вычислений при выполнении программы на C ++? - PullRequest
0 голосов
/ 15 мая 2018

Я пытался сделать следующие вычисления, но обнаружил, что вычисления не дают правильного результата.У меня есть следующие сомнения в том, что когда мой компьютер выполняет вычисления a * b, какой тип данных используется для временного хранения результата вычисления перед выполнением модуля.Как определяется тип данных, в котором он хранит результат?Пожалуйста, дайте мне знать об источнике информации.

#include <iostream>
using namespace std;

int main()
{
    long long int a=1000000000000000000; // 18 zeroes
    long long int b=1000000000000000000;
    long long int c=1000000007; 
    long long int d=(a*b)%c;
    cout<<a<<"\n"<<b<<"\n"<<c<<"\n"<<d;
}

Edit1: этот код также дает неправильный вывод

#include <iostream>
using namespace std;

int main()
{
    int a=1000000000; // 9 zeroes
    int b=1000000000;
    long long int c=1000000007; 
    long long int d=a*b%c;
    cout<<a<<"\n"<<b<<"\n"<<c<<"\n"<<d;
}

Ответы [ 2 ]

0 голосов
/ 15 мая 2018

Как определяется тип данных, в котором он хранит результат?

Правила довольно сложны и сложны в целом, но в данном конкретном случае это просто.a*b имеет тип long long, и, поскольку a*b переполняет, программы имеют неопределенное поведение.

Вы можете использовать эквивалентную формулу для вычисления правильного результата (без переполнения):

(a * b) % c == ((a % c) * (b % c)) % c

Не могли бы вы также предложить, как выбрать смешанные типы данных, и сообщить о вашем источнике информации

Интерес представляет: https://en.cppreference.com/w/cpp/language/implicit_conversion Стандартные правилак сожалению, еще более сложны.

Так как некоторые предложения:

  • никогда не смешивают без знака и со знаком.
  • обратите внимание, что типы, меньшие чем int, будут переведены в int или unsigned.
  • для типа T, равного или большего чем int, тогда T op T будет иметь тип T.Это то, к чему вы должны стремиться в своих выражениях.(то есть оба оператора одного типа: int, long или long long.
  • избегают unsigned типов. К сожалению, это невозможно с текущим дизайном стандартной библиотеки (std::size_t sigh)
  • избегайте long, так как его ширина отличается между текущими основными компиляторами и платформами
  • , если вы заботитесь о ширине целочисленного типа данных, тогда избегайте int long long long и тому подобного ивсегда используйте целочисленные типы фиксированной ширины (std::int32_t std::int64_t и т. д.). Полностью игнорируйте, что технически эти типы являются необязательными.
0 голосов
/ 15 мая 2018

Насколько я понимаю, long long должен содержать не менее 64 бит, но каждое 1000000000000000000 - это 60-битное число, поэтому a * b даст результат, который превосходит любое целочисленное представление, поддерживаемое компилятором. Возможно, вы думали, что 1000000000000000000 был двоичным?

...