Консультация № 148952
30.10.2008, 08:36
0.00 руб.
0 4 1
Здравствуйте уважаемые эксперты! Помогите пожалуйста в решении следующей задачи: Создать абстрактный тип данных (структура) - вектор, который имеет указатель на double и число элементов. Определить функцию, которая выделяет память для массива и инициализирует данные. Определить 2 функции, отличающиеся только спецификатором inline, которые получают элемент массива, использовать их при вычислении средне квадратичного отклонения. Освободить память. Сравнить время вычисления.

Обсуждение

Неизвестный
30.10.2008, 12:40
общий
30.10.2008, 17:36
это ответ
Здравствуйте, Sharkerr!

немного математики: среднеквадратичное отклонение ( = квадратный корень из дисперсии) в общем случае задается через математическое ожидание, которое требует плотности распределения вероятности по значениям. при равновероятных значениях мат ожидание превращается в среднее арифметическое. будем для простоты считать, что у нас именно такой случай
по определнию дисперсия это D[X] = M[(X - M[X])^2], путем преобразований можно получить более удобную дял вычисления:
D[X] = M[X^2] - (M[X])^2 - это и будем вычислять, потом извлечем корень

теперь по коду:
компилировалось в MS Visual Studio, если у Вас другая среда разработки - то как посчитать время решайте сами

"функция, которая выделяет память для массива и инициализирует данные." - это конструктор класса Array
"Освободить память" - делается, соответственно, в деструкторе.

Число в Array arr(5000000); можете сделать меньше, если комп не очень быстрый. для относительно честного результата с 2мя значащими цифрами нужно что-бы считало не менее 10 миллисекунд.

Удачи!

Приложение:
#include <math.h>
#include <stdlib.h>
#include <stdio.h>

// для вычисления точного времени
#include <windows.h>
#include <Mmsystem.h>
#pragma comment(lib, "Winmm.lib")

class Array
{
public:
Array(unsigned sz);
~Array();

unsigned size() const { return size_; }

// inline, т.к. реализация прямо в описании
double operator[] (unsigned idx) const { return data_[idx]; }

// скорее всего не inline, но особо умный компилятор может решить по своему
double get(unsigned idx) const;

private:
unsigned size_;
double* data_;
};

Array::Array(unsigned sz)
{
data_ = new double[size_ = sz];
for(unsigned idx = 0; idx < size_; ++idx)
data_[idx] = (double)(rand() % 20 - 10);
}

Array::~Array()
{
delete data_;
}

double Array::get(unsigned idx) const
{
return data_[idx];
}


double calc1(const Array& arr)
{
double m1 = 0; // сумма
double m2 = 0; // сумма квадратов
for(unsigned idx = 0; idx < arr.size(); ++idx){
m1 += arr[idx];
m2 += arr[idx] * arr[idx];
}
m1 /= arr.size();
m2 /= arr.size();
return sqrt(m2 - m1 * m1);
}

double calc2(const Array& arr)
{
double m1 = 0; // сумма
double m2 = 0; // сумма квадратов
for(unsigned idx = 0; idx < arr.size(); ++idx){
m1 += arr.get(idx);
m2 += arr.get(idx) * arr.get(idx);
}
m1 /= arr.size();
m2 /= arr.size();
return sqrt(m2 - m1 * m1);
}

void main(void)
{
Array arr(5000000);

// для получения времени с точностью до 1мс
timeBeginPeriod(1);

DWORD start = timeGetTime();
double res1 = calc1(arr);
DWORD finish1 = timeGetTime();
double res2 = calc2(arr);
DWORD finish2 = timeGetTime();


printf("\tInline time = %d ms, res = %.6f\nNOT\tinline time = %d ms, res = %.6f\n",finish1 - start, res1, finish2 - finish1, res2);
}
Неизвестный
30.10.2008, 13:12
общий
В общем проверить время будет очень трудно. Умный компилятор в релизе не просто инлайнит get, но вообще замечает, что функции calc1 и calc2 делаю одно и тоже и генерит только одну функцию, которая и вызывается независимо от того, что указано в коде. в дебаге не инлайнит ничего.
Как бороться с этим даже не знаю.
давно
Профессор
230118
3054
31.10.2009, 23:15
общий
Sharkerr:
Как - отключить "умность". То есть отключить оптимизацию, Inline function expansion - only inline
давно
Профессор
230118
3054
31.10.2009, 23:27
общий
Alеxandr:
Или есть microsoft-specific
__declspec(noinline)
__declspec(noinline) tells the compiler to never inline a particular member function (function in a class).
Форма ответа