Почему мой код выводит неверные результаты?Целочисленное переполнение? - PullRequest
0 голосов
/ 26 сентября 2018

Предположим, что у нас есть 15 чисел от [0] до [14], которые удовлетворяют:

a[0]=4
a[i]=pow(sqrt(a[i-1])*2-1, 2) for i>=1 and i<=14

Мне нужно распечатать все значения от [0] до [14], каждое число находится в одной строке , поэтому я пишу следующий код (C ++, Code :: Blocks):

#include <iostream>
#include <cmath>
using namespace std;
#define maxN 15
int i[maxN]; int n=15;
int main()
{
    i[0]=2;
    cout<<4<<endl;
    for (int k=1; k<n; k++){
        i[k]=i[k-1]*2-1;
        cout<<pow(i[k],2)<<"\t"<<endl;
    }
    return 0;
}

Результат:

4
9
25
81
289
1089
4225
16641
66049
263169
1.05062e+006
4.1984e+006
1.67854e+007
6.71252e+007
2.68468e+008

Последние пять чисел не верны (из-за переполнения целых чисел).

В приведенном выше цикле for я меняю строку

cout<<pow(i[k],2)<<"\t"<<endl;

на

cout<<(long) pow(i[k],2)<<"\t"<<endl;

На этот раз результат:

4
9
24
81
289
1089
4224
16641
66048
263168
1050625
4198400
16785408
67125248
268468224

После того, как я проверил вручную, я понял, что многие числа по-прежнему неверны: 24;4224;66048;263168;4198400;16785408;67125248;268468224 (все они на 1 ниже, чем правильные числа).Что я должен сделать, чтобы это исправить?

Ответы [ 2 ]

0 голосов
/ 26 сентября 2018

Что я должен сделать, чтобы это исправить?

изменить

cout<<pow(i[k],2)<<"\t"<<endl;

на

cout<<i[k]*i[k]<<"\t"<<endl;

pow - с плавающей запятойфункция, которая может быть неточной.Обратите внимание, что в вашем случае есть что-то странное: если pow использует 64-битные двойные значения IEEE-754, он должен печатать точные цифры для вашего ввода.Поэтому, возможно, вы используете 32-битные float числа.

0 голосов
/ 26 сентября 2018

1.05062e + 006 и 1050625 - это одинаковые значения, напечатанные по-разному.pow(i[k],2) возвращает тип с плавающей запятой , здесь не происходит переполнения целых чисел, а скорее происходит округление при преобразовании такой плавающей запятой в long.

Формат Xe+Y называется научное обозначение , его значение X * 10 ^ Y.По умолчанию std::printf и std::ostream::operator<< печатает значения с плавающей запятой, превышающие определенную границу в их научной нотации.См. https://en.cppreference.com/w/cpp/io/manip/fixed для получения дополнительной информации.

...