Отнормировать вещественный масиив

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

Ну и вариант который не знает про типы вообще ничего. С++14, на более старых вариантах код получится более кучерявым.

Код: Выделить всё

#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <deque>

namespace detail {
// generic abs algorithm
template<typename T> constexpr auto abs(const T& value) -> T
{
  return value < T{} ? -value : value;
}
}

template<typename T> constexpr auto abs(const T& value) -> T
{
  using std::abs;
  using detail::abs;
  return abs(value);
}

template <typename Iterator> void Norm(Iterator begin, Iterator end)
{
  auto maxElItr = std::max_element(begin, end, [](auto lho, auto rho) -> bool {
    return abs(lho) < abs(rho);
  });
  if (maxElItr != end) {
    auto maxEl = abs(*maxElItr);
    auto zero = decltype(maxEl) {};
    if (zero < maxEl) {
      for (auto itr = begin; itr != end; ++itr) {
        *itr /= maxEl;
      }
    }
  }
}

int main()
{
  double a[] = {1.2, 1.2, 1.2, 1.2, 1.2 };
  std::deque<float> b = { 0.2f, 1.2f, 0.0f, 3.0f, 0.8f };
  Norm(a, a + sizeof(a) /sizeof(a[0]));
  Norm(b.begin(), b. end());
  return 0;
}
2B OR NOT(2B) = FF
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Во-первых это не нормирование, т.к если в массиве числа в диапазоне [0.2 .. 1.0], то после такого нормирования они будут замаплены на диапазон [0..1], что неверно.
Только приведение к диапазону [0..1] и есть нормирование. Всё остальное по определению нормированием не является.
Во-вторых для массива единичной длины
И как же Вы собираетесь нормировать этот вырожденный случай?
Норма нуля по определению это 0, так как с точки зрения математики норма это расстояние точки от нуля в метрическом пространстве. Поэтому в результате нормирования ноль должен быть отображен на ноль, поскольку ноль это инвариант у операции "норма".
А где этот 0 на шкале? В случае температуры это ноль по Фаренгейту, Цельсию, или абсолютный? А в случае потенциала это потенциал Земли, корпуса устройства, Солнца, или может галактического ядра? А расстояние до ноля - это само число, для 100 это 100, а ни как не 1. Но есть величины размерные и безразмерные, нормированные величины - это безразмерные отклонения от минимума.
Кстати, то же самое будет если все элементы в массиве равны.
Тоже вырожденный случай, константу не нормируют.
чтобы передавать туда std::vector<double>
По условию у нас массив.
Ну и в третьих оно всегда читает первый элемент, даже у массива нулевой длины,
А ничего, что я предупредил о том, что функция не проверяет корректность параметров?
Ну и по стилю: непонятно зачем делать тип элемента шаблонным параметром, когда можно сделать таковым тип самой последовательности, чтобы передавать туда std::vector<double>, например.

Код: Выделить всё

template <typename t> void f(t Data)
{
 // Ну ка определите здесь базовый тип для t в случае, когда t - тип массива?
}
Более того, линейный параметр-массив - это всегда просто указатель, чей sizeof определяется только разрядностью системы и определить даже количество элементов становится не возможно, так как sizeof(Data)/sizeof(Data[0]) не имеет смысла.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Во-вторых для массива единичной длины
И как же Вы собираетесь нормировать этот вырожденный случай?
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Норма нуля по определению это 0, так как с точки зрения математики норма это расстояние точки от нуля в метрическом пространстве. Поэтому в результате нормирования ноль должен быть отображен на ноль, поскольку ноль это инвариант у операции "норма".
А где этот 0 на шкале? В случае температуры это ноль по Фаренгейту, Цельсию, или абсолютный? А в случае потенциала это потенциал Земли, корпуса устройства, Солнца, или может галактического ядра? А расстояние до ноля - это само число, для 100 это 100, а ни как не 1. Но есть величины размерные и безразмерные, нормированные величины - это безразмерные отклонения от минимума.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Кстати, то же самое будет если все элементы в массиве равны.
Тоже вырожденный случай, константу не нормируют.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Ну и в третьих оно всегда читает первый элемент, даже у массива нулевой длины,
А ничего, что я предупредил о том, что функция не проверяет корректность параметров?
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Ну и по стилю: непонятно зачем делать тип элемента шаблонным параметром, когда можно сделать таковым тип самой последовательности, чтобы передавать туда std::vector<double>, например.

Код: Выделить всё

template <typename t> void f(t Data)
{
 // Ну ка определите здесь базовый тип для t в случае, когда t - тип массива?
}
Более того, линейный параметр-массив - это всегда просто указатель, чей sizeof определяется только разрядностью системы и определить даже количество элементов становится не возможно, так как sizeof(Data)/sizeof(Data[0]) не имеет смысла.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

чтобы передавать туда std::vector<double>
По условию у нас массив.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

Сионист писал(а):Только приведение к диапазону [0..1] и есть нормирование. Всё остальное по определению нормированием не является.
По какому определению? Но в любом случае, деление всех элементов на норму вектора вполне отображает все элементы в диапазон [0..1]. Умножение всех элементов на 0 тоже отображает, т.к. ноль входит в диапазон [0..1].
Сионист писал(а): И как же Вы собираетесь нормировать этот вырожденный случай?
Вектор единичной размерности это тоже вектор.
Сионист писал(а): А где этот 0 на шкале? В случае температуры это ноль по Фаренгейту, Цельсию, или абсолютный?
Отображение Цельсия на Фаренгейта это не нормирование, а аффинное преобразование.
Кстати, то же самое будет если все элементы в массиве равны.
Сионист писал(а): Тоже вырожденный случай, константу не нормируют.
То есть вектор [10 10 10] нельзя нормировать?
Сионист писал(а): По условию у нас массив.
std::vector и std::deque это тоже массивы. Стоимость доступа к произвольному элементу у них O(1).
Сионист писал(а): А ничего, что я предупредил о том, что функция не проверяет корректность параметров?
Массив нулевой длины вполне корректен. И вообще так максимум в последовательности не ищут. Правильный алгоритм - присвоить переменной std::numeric_limits<T>::min(), и потом сравнивать с ней. После первого же сравнения это значение будет переписано, так как любое возможное значение будет больше или равно. Или не будет, если в последовательности ноль элементов.
Сионист писал(а): Более того, линейный параметр-массив - это всегда просто указатель, чей sizeof определяется только разрядностью системы и определить даже количество элементов становится не возможно, так как sizeof(Data)/sizeof(Data[0]) не имеет смысла.

Размер локального массива, тем не менее, определить в compile-time можно.
2B OR NOT(2B) = FF
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

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

Вот скажи, с каких это пор преобразование, которое не является инвариантным относительно ноля является нормированием? Хоть бы почитал, что такое нормирование на вики, если интуитивного представления об этом нет.

P.S. А в коде у тебя реальный треш. Похоже, ты не понимаешь, зачем нужны шаблоны.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Ответить