Почему в массив c++ записывается некорректное значение?

210
09 февраля 2018, 21:04
#include <iostream>
#include <cstdlib>
#include <cmath>
using namespace std;
int main()
{
    int n, j = 0;
    cout << "Amount of numbers: ";
    cin >> n;
    const int length = n;
    int numbers[length];
    if (length >= 1) {
        // Элементы с чётными индексами получают значение индекса, с нечётными - квадрата индекса
        while (j < length) {
            if (j % 2 == 0){
                numbers[j] = j;
            }
            else {
                numbers[j] = pow(j, 2);
            }
            j++;
        }
        // Выводим элементы массива
        j = 0;
        while (j < length) {
            cout << numbers[j] << endl;
            j++;
        }
    }
    system("pause>nul");
    return 0;
}

Answer 1

Типом возвращаемого значения функции std::pow() является либо float, либо double, либо long double, т.е. возвращается значение с плавающей точкой.

В вашем примере, вы передаёте два аргумента типа int, и они оба внутри функции pow приводятся к типу double, и возвращаемое значение также имеет тип double.

Затем в вашем примере значение, возвращённое функцией pow и имеющее тип double приводится к типу int. В C++ типы с плавающей точкой приводятся к целочисленным типам путём отбрасывания дробной части (так называемое округление в сторону нуля).

Так процесс возведения в степень осуществляется в числах с плавающей точкой, то нужно быть готовым к тому, что результат получится не совсем точным. Например, если точный результат некоторого вычисления равен 25, то в общем случае результирующее значение может оказаться равным, например, 24.999999999999996. Приведение этого значения к типу int отбросит дробную часть и в результате получится значение 24.

Мне не удалось повторить вывод вашей программы, используя функцию std::pow() из заголовочного файла <cmath> (вероятно потому, что я использовал Visual Studio). Предполагаю, что, возможно, в вашем случае реализация функции pow() имеет примерно такой вид:

template <typename T1, typename T2>
double pow_bad(T1 base, T2 exp)
{
    return std::exp( double(exp) * std::log(double(base)) );
}

или что-либо подобное. Один из возможных результатов работы приведённой выше функции на ваших входных данных будет таким:

i^2.0 = pow_bad(i, 2) int( pow_bad(i, 2) )
1^2.0 = 1 1
3^2.0 = 9.0000000000000018 9
5^2.0 = 24.999999999999996 24
7^2.0 = 48.999999999999993 48
9^2.0 = 81.000000000000028 81
11^2.0 = 121.00000000000003 121
13^2.0 = 169 169

Хотя вывод и не совпадает в точности с выводом вашей программы, но суть, думаю, понятна.

Попробуйте с помощью отладчика зайти внутрь функции pow и посмотреть как она устроена внутри. Возможно, что ничего интересного там не будет, но попробовать стоит.

Answer 2

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

const int length = n;
int numbers[length];

на

int *numbers=  new int[n]

и перед

system("pause>nul");

добавить

delete[] numbers

почитайте про динамическую память в с++ https://ru.wikipedia.org/wiki/New_(C%2B%2B)

Answer 3

Функция pow не умножает значение x n раз, так как она также должна вычислять степень с использованием дробных показателей. Используйте другую функцию или напишите свою. Функция pow (возможно, используя логарифмы) использует значения с плавающей запятой для вычисления значения степени, поэтому с int работает не так, как вам кажется, что она должна работать. Также ваша функция для вычисления степени int будет явно работать быстрее.

Answer 4

Замените-ка для проверки

numbers[j] = pow(j, 2);

на

numbers[j] = j*j;

Потому что если не считать использованного нестандартного расширения, это единственное слабое место...

P.S. Не понимаю две любви студентов - к float вместо double и к pow там, где она совсем ни к чему...

READ ALSO
Как отключить автовоспроизведение в Selenium chromedriver?

Как отключить автовоспроизведение в Selenium chromedriver?

Использую chromedriver для тестирования, и необходимо отключить автовоспроизведение всех видеоКакие есть варианты это решить?

192
Антивирус блокирует мою java программу

Антивирус блокирует мою java программу

Всем приветУ меня есть прога на java которая закачивает файлы с сервера и запускает их (лаунчер для игры) Ее я компилю в jar и с помощью launc4j превращаю...

217
сокеты java проблемы с передачей данных

сокеты java проблемы с передачей данных

ЗдравствуйтеПишу клиент-серверную игру на сокетах

232
Как сделать Eclipse 4.7 более отзывчивым server-jre-1.8 oracle&hellip; Linux(Ubuntu)?

Как сделать Eclipse 4.7 более отзывчивым server-jre-1.8 oracle… Linux(Ubuntu)?

Пытаюсь заставить работать Эклипс 47 быстрее, не во время загрузки а в процессе длительной работы с ним

198