auto x = numbers[i]; // следующий элемент последовательности
// Воспользуемся тем фактом, что логические операции возвращают 0 или 1.
negatives += x < 0.0;
positives += x > 0.0;
}
// Без приведения к double будет деление в целых числах.
return double(positives) / negatives;
}
// П.2: тестирование функции из п.1 на заранее заданных массивах.
bool test_pn_ratio()
{
const double test1[] = { 4, 1, 100, 0, 20, 0, -1, -2, 3, -6 };
// sizeof возвращает размер статического массива в байтах
// (!) при этом массив должен быть виден в данном контексте непосредственно,
// (!) иначе программист рискует получить вместо размера массива размер указателя на него
if (pn_ratio(test1, sizeof(test1) / sizeof(double)) != 5.0 / 3.0)
return false;
const double test2[] = { -40, -2, -111, 42, 0, 0, 2, -1000, -4 };
if (pn_ratio(test2, sizeof(test2) / sizeof(double)) != 2.0 / 5.0)
return false;
// Все проверки прошли успешно.
return true;
}
// П.3: считывание чисел с потока ввода.
double pn_ratio(istream &in)
{
// Счётчики положительных и отрицательных чисел.
size_t positives = 0, negatives = 0;
for (double x; in >> x;)
{
if (x < 0.0)
++negatives;
else if (x > 0.0)
++positives;
}
// Без приведения к double будет деление в целых числах.
return double(positives) / negatives;
}
int main()
{
// Тестирование варианта обработки данных для массива.
cout << test_pn_ratio() << endl;
// Вариант для обработки данных с потока ввода.
const auto result = pn_ratio(cin);
cout << "\nResult: " << result << endl;
return EXIT_SUCCESS;
}
0505-static_array_begin_end.cpp
// static_array_begin_end.cpp
// Использование std::begin и std::end для получения границ диапазона статического массива.
#include
#include // begin, end
using namespace std;
// Заполняет [begin, end) квадратами индексов.
void fill_with_squares(float* begin, float* end)
{
// Количество элементов равно разности указателей.
for (size_t i = 0; i != end - begin; ++i)
begin[i] = i * i;
}
// Выводим array в консоль.
void print_array(float* begin, float* end)
{
while (begin != end)
cout << *begin++ << '\n';
}
int main()
{
// Локальный статический массив. Его размер виден только внутри main.
float squares[100];
// begin(squares) возвращает указатель на первый элемент массива, а
// end(squares) возвращает указатель на фиктивный элемент, следующий за последним элементом массива.
fill_with_squares(begin(squares), end(squares));
// Вывести в консоль.
print_array(begin(squares), end(squares));
}
0510-euclid_norm.cpp
// euclid_norm.cpp
// Евклидова норма последовательности как многомерного вектора.
// Пример: { 1, -5, 2, 20, -13 } -> (1+25+4+400+169)1/2 = 24.4744765.
#include
#include
#include
using namespace std;
/// Чувствительность к погрешности при проверке нормы.
const double TOLERANCE = 1e-6;
// Сравнение двух значений на примерное равенство
// с заданным уровнем относительной разности tolerance.
// В данном примере используется при тестировании.
bool almost_equal(double x1, double x2, double tolerance = TOLERANCE)
{
return abs(x1 - x2) <= tolerance * fmax(abs(x1), abs(x2));
}
// П.1: обработка произвольного массива, переданного как адрес + размер,
// size_t -- стандартный тип (определён в Стандартной библиотеке C),
// предназначенный для хранения размеров массивов.
double euclid_norm(const double a[], size_t n)
{
double s = 0.0;
for (size_t i = 0; i < n; ++i)
s += a[i] * a[i];
return sqrt(s);
}
// П.2: тестирование функции из п.2 на заранее заданных массивах.
bool test_euclid_norm()
{
const double test1[] = { 4, 1, 0, 3, 0, -1, -2, -6 };
// sizeof возвращает размер статического массива в байтах
// (!) при этом массив должен быть виден в данном контексте непосредственно,
// (!) иначе программист рискует получить вместо размера массива размер указателя на него
if (!almost_equal(
euclid_norm(test1, sizeof(test1) / sizeof(double)),
8.18535277))
return false;
const double test2[] = { -40, -2, -111, 42, 2, -1000, -4 };
if (!almost_equal(
euclid_norm(test2, sizeof(test2) / sizeof(double)),
1007.823893))
return false;
// Все тесты прошли успешно.
return true;
}
// П.3: считывание чисел с потока ввода.
double euclid_norm(istream &in)
{
double s = 0.0;
for (double x; in >> x;)
s += x * x;
return sqrt(s);
}
int main()
{
// Запуск тестов из п.2.
cout << test_euclid_norm() << endl;
// Запуск функции из п.3.
const auto result = euclid_norm(cin);
cout << "\nResult: " << result << endl;
return EXIT_SUCCESS;
}
0520-euclid_norm_2.cpp
// euclid_norm_2.cpp
// Евклидова норма последовательности как многомерного вектора.
// Пример: { 1, -5, 2, 20, -13 } -> (1+25+4+400+169)1/2 = 24.4744765.
#include
#include
#include
#include // строковые потоки ввода-вывода
using namespace std;
/// Чувствительность к погрешности при проверке нормы.
const double TOLERANCE = 1e-6;
// Сравнение двух значений на примерное равенство
// с заданным уровнем относительной разности tolerance.
// В данном примере используется при тестировании.
bool almost_equal(double x1, double x2, double tolerance = TOLERANCE)
{
return abs(x1 - x2) <= tolerance * fmax(abs(x1), abs(x2));
}
// П.1: обработка произвольного массива, переданного как адрес + размер,
// size_t -- стандартный тип (определён в Стандартной библиотеке C),
// предназначенный для хранения размеров массивов.
double euclid_norm(const double a[], size_t n)
{
double s = 0.0;
for (size_t i = 0; i < n; ++i)
s += a[i] * a[i];
return sqrt(s);
}
// П.2: тестирование функции из п.2 на заранее заданных массивах.
bool test_euclid_norm_array()
{
const double test1[] = { 4, 1, 0, 3, 0, -1, -2, -6 };
// sizeof возвращает размер статического массива в байтах
// (!) при этом массив должен быть виден в данном контексте непосредственно,
// (!) иначе программист рискует получить вместо размера массива размер указателя на него
if (!almost_equal(
euclid_norm(test1, sizeof(test1) / sizeof(double)),
8.18535277))
return false;
const double test2[] = { -40, -2, -111, 42, 2, -1000, -4 };
if (!almost_equal(
euclid_norm(test2, sizeof(test2) / sizeof(double)),
1007.823893))
return false;
// Все тесты прошли успешно.
return true;
}
// П.3: считывание чисел с потока ввода.
double euclid_norm(istream &in)
{
double s = 0.0;
for (double x; in >> x;)
s += x * x;
return sqrt(s);
}
// Дополнение: тестирование функции из п.3 на заранее заданных последовательностях.
bool test_euclid_norm_stream()
{
stringstream ts;
ts << 4 << ' ' << 1 << ' ' << 0 << ' ' << 3 << ' ';
ts << 0 << ' ' << -1 << ' ' << -2 << ' ' << -6;
if (!almost_equal(euclid_norm(ts), 8.18535277))
return false;
ts.clear(); // сбросить флаг конца файла
ts.seekp(0); // сбросить позицию записи в поток на начало
ts.seekg(0); // сбросить позицию чтения из потока на начало
ts << -40 << ' ' << -2 << ' ' << -111 << ' ' << 42 << ' ';
ts << 2 << ' ' << -1000 << ' ' << -4;
if (!almost_equal(euclid_norm(ts), 1007.823893))
return false;
// Все тесты прошли успешно.
return true;
}
int main()
{
// Запуск тестов из п.2.
cout << test_euclid_norm_array() << endl;
// Запуск тестов для функции из п.3.
cout << test_euclid_norm_stream() << endl;
return EXIT_SUCCESS;
}
0530-max_duplicates_sequence.cpp
// max_duplicates_sequence.cpp
// Определить длину максимальной подпоследовательности, состоящей из идущих подряд равных элементов.
// Пример: { 1, 2, 3, 3, 0, 0, 0, 1, 2 } -> 3 (три нуля подряд).
#include
#include
#include // строковые потоки для тестирования п.4
using namespace std;
// Вычислить максимум двух целых чисел.
inline size_t max(size_t a, size_t b)
{
return a < b? b: a;
}
// П.1: обработка произвольного массива, переданного как адрес + размер
size_t max_duprun(const double a[], size_t n)
{
if (n == 0)
return 0;
// По крайней мере, один элемент в массиве есть.
size_t max_run = 1; // максимальная длина на данный момент
size_t cur_run = 1; // текущая длина
for (size_t i = 1; i < n; ++i)
{
if (a[i] != a[i - 1]) // соседние элементы не равны
cur_run = 1;
else // продолжается подпоследовательность равных
++cur_run;
max_run = max(max_run, cur_run);
}
return max_run;
}
// П.2: тестирование функции из п.1 на заданном массиве с заданным результатом.
bool test_max_duprun_array(const double a[], size_t n, size_t result)
{
return result == max_duprun(a, n);
}
// П.3: считывание чисел с потока ввода.
size_t max_duprun(istream &in)
{
size_t max_run = 0; // максимальная длина на данный момент
double x, prev_x; // последнее и предпоследнее прочитанные числа
Do'stlaringiz bilan baham: |