Округление с произвольным шагом

Sep 01, 2015 10:37


Написал функцию которая округляет число не до определенного количества десятичных разрядов, а с любой дискретностью. Например, если округлить 1,5 до 0,33, получится 1,32 или 1,65 в зависимости от метода округления.

Вызов функций выглядит так:

МетодыОкругления.ОкруглитьСШагом(1.5, 0.33, МетодыОкругления.КМеньшему); //должно получиться 1.32
МетодыОкругления.Округлить(2.5, 0, МетодыОкругления.Математический); //должно получиться 3


Надо завести в 1С перечисление МетодыОкругления со значениями:
  • Математический
  • Банковский
  • КМеньшемуПоМодулю
  • КМеньшему
  • КБольшемуПоМодулю
  • КБольшему


В модуле менеджера этого перечисления прописать функции:

Функция Округлить(Число, ДесятичныхЗнаков, МетодОкругления)  Экспорт
 Возврат ОкруглитьСШагом(Число, Pow(10, -ДесятичныхЗнаков), МетодОкругления);
КонецФункции

Функция ОкруглитьСШагом(Число, Шаг, МетодОкругления) Экспорт
 Перем Результат;
 Перем СредняяТочка;

//2,5 → 2; 3,5 → 3; -2,5 → -2; -3,5 → -3
 Результат = Цел(Число / Шаг) * Шаг;

Если МетодОкругления = Математический Тогда
  //2,5 → 3; 3,5 → 4; -2,5 → -3; -3,5 → -4 (0,5 в бо́льшую по модулю сторону)
  Если Число > 0 Тогда
   СредняяТочка = (Цел(Число / Шаг) + 0.5) * Шаг;

Если Число >= СредняяТочка Тогда
    Результат = Результат + Шаг;
   КонецЕсли;
  ИначеЕсли Число < 0 Тогда
   СредняяТочка = (Цел(Число / Шаг) - 0.5) * Шаг;

Если Число <= СредняяТочка Тогда
    Результат = Результат - Шаг;
   КонецЕсли;
  КонецЕсли;

ИначеЕсли МетодОкругления = Банковский Тогда
  //2,5 → 2; 3,5 → 4; -2,5 → -2; -3,5 → -4 (0,5 к ближайшему чётному)
  Если Число > 0 Тогда
   СредняяТочка = (Цел(Число / Шаг) + 0.5) * Шаг;

Если Число > СредняяТочка Тогда
    Результат = Результат + Шаг;
   ИначеЕсли
    Число = СредняяТочка И
    Результат % (2 * Шаг) <> 0
   Тогда
    Результат = Результат + Шаг;
   КонецЕсли;
  ИначеЕсли Число < 0 Тогда
   СредняяТочка = (Цел(Число / Шаг) - 0.5) * Шаг;

Если Число < СредняяТочка Тогда
    Результат = Результат - Шаг;
   ИначеЕсли
    Число = СредняяТочка И
    Результат % (2 * Шаг) <> 0
   Тогда
    Результат = Результат - Шаг;
   КонецЕсли;
  КонецЕсли;

ИначеЕсли МетодОкругления = КМеньшемуПоМодулю Тогда
  //2,5 → 2; 3,5 → 3; -2,5 → -2; -3,5 → -3

ИначеЕсли МетодОкругления = КМеньшему Тогда
  //2,5 → 2; 3,5 → 3; -2,5 → -3; -3,5 → -4
  Если Результат <> Число Тогда
   Если Число < 0 Тогда
    Результат = Результат - Шаг;
   КонецЕсли;
  КонецЕсли;

ИначеЕсли МетодОкругления = КБольшемуПоМодулю Тогда
  //2,5 → 3; 3,5 → 4; -2,5 → -3; -3,5 → -4
  Если Результат <> Число Тогда
   Если Число > 0 Тогда
    Результат = Результат + Шаг;
   Иначе
    Результат = Результат - Шаг;
   КонецЕсли;
  КонецЕсли;

ИначеЕсли МетодОкругления = КБольшему Тогда
  //2,5 → 3; 3,5 → 4; -2,5 → -2; -3,5 → -3
  Если Результат <> Число Тогда
   Если Число > 0 Тогда
    Результат = Результат + Шаг;
   КонецЕсли;
  КонецЕсли;

Иначе
  ВызватьИсключение "Неверное значение параметра МетодОкругления.";
 КонецЕсли;

Возврат Результат;
КонецФункции

Процедура ВыполнитьТесты() Экспорт
  Перем Результат;

Результат = Истина;

Результат = ТестОкруглить(0, 0, Математический, 0) И Результат;
 Результат = ТестОкруглить(2.5, 0, Математический, 3) И Результат;
 Результат = ТестОкруглить(3.5, 0, Математический, 4) И Результат;
 Результат = ТестОкруглить(-2.5, 0, Математический, -3) И Результат;
 Результат = ТестОкруглить(-3.5, 0, Математический, -4) И Результат;
 Результат = ТестОкруглить(0.450, 1, Математический, 0.5) И Результат;
 Результат = ТестОкруглить(0.451, 1, Математический, 0.5) И Результат;
 Результат = ТестОкруглить(-0.449, 1, Математический, -0.4) И Результат;
 Результат = ТестОкруглить(-0.450, 1, Математический, -0.5) И Результат;
 Результат = ТестОкруглить(-0.451, 1, Математический, -0.5) И Результат;
 Результат = ТестОкруглить(0.550, 1, Математический, 0.6) И Результат;
 Результат = ТестОкруглить(0.551, 1, Математический, 0.6) И Результат;
 Результат = ТестОкруглить(-0.549, 1, Математический, -0.5) И Результат;
 Результат = ТестОкруглить(-0.550, 1, Математический, -0.6) И Результат;
 Результат = ТестОкруглить(-0.551, 1, Математический, -0.6) И Результат;
 Результат = ТестОкруглить(0.1, 0, Математический, 0) И Результат;
 Результат = ТестОкруглить(0.6, 0, Математический, 1) И Результат;
 Результат = ТестОкруглить(1, 0, Математический, 1) И Результат;

Результат = ТестОкруглить(0, 0, Банковский, 0) И Результат;
 Результат = ТестОкруглить(2.5, 0, Банковский, 2) И Результат;
 Результат = ТестОкруглить(3.5, 0, Банковский, 4) И Результат;
 Результат = ТестОкруглить(-2.5, 0, Банковский, -2) И Результат;
 Результат = ТестОкруглить(-3.5, 0, Банковский, -4) И Результат;
 Результат = ТестОкруглить(0.450, 1, Банковский, 0.4) И Результат;
 Результат = ТестОкруглить(0.451, 1, Банковский, 0.5) И Результат;
 Результат = ТестОкруглить(-0.449, 1, Банковский, -0.4) И Результат;
 Результат = ТестОкруглить(-0.450, 1, Банковский, -0.4) И Результат;
 Результат = ТестОкруглить(-0.451, 1, Банковский, -0.5) И Результат;
 Результат = ТестОкруглить(0.550, 1, Банковский, 0.6) И Результат;
 Результат = ТестОкруглить(0.551, 1, Банковский, 0.6) И Результат;
 Результат = ТестОкруглить(-0.549, 1, Банковский, -0.5) И Результат;
 Результат = ТестОкруглить(-0.550, 1, Банковский, -0.6) И Результат;
 Результат = ТестОкруглить(-0.551, 1, Банковский, -0.6) И Результат;
 Результат = ТестОкруглить(0.1, 0, Банковский, 0) И Результат;
 Результат = ТестОкруглить(0.6, 0, Банковский, 1) И Результат;
 Результат = ТестОкруглить(1, 0, Банковский, 1) И Результат;

Результат = ТестОкруглить(0, 0, КМеньшемуПоМодулю, 0) И Результат;
 Результат = ТестОкруглить(2.5, 0, КМеньшемуПоМодулю, 2) И Результат;
 Результат = ТестОкруглить(3.5, 0, КМеньшемуПоМодулю, 3) И Результат;
 Результат = ТестОкруглить(-2.5, 0, КМеньшемуПоМодулю, -2) И Результат;
 Результат = ТестОкруглить(-3.5, 0, КМеньшемуПоМодулю, -3) И Результат;
 Результат = ТестОкруглить(0.450, 1, КМеньшемуПоМодулю, 0.4) И Результат;
 Результат = ТестОкруглить(0.451, 1, КМеньшемуПоМодулю, 0.4) И Результат;
 Результат = ТестОкруглить(-0.449, 1, КМеньшемуПоМодулю, -0.4) И Результат;
 Результат = ТестОкруглить(-0.450, 1, КМеньшемуПоМодулю, -0.4) И Результат;
 Результат = ТестОкруглить(-0.451, 1, КМеньшемуПоМодулю, -0.4) И Результат;
 Результат = ТестОкруглить(0.1, 0, КМеньшемуПоМодулю, 0) И Результат;
 Результат = ТестОкруглить(0.6, 0, КМеньшемуПоМодулю, 0) И Результат;
 Результат = ТестОкруглить(1, 0, КМеньшемуПоМодулю, 1) И Результат;

Результат = ТестОкруглить(0, 0, КМеньшему, 0) И Результат;
 Результат = ТестОкруглить(2.5, 0, КМеньшему, 2) И Результат;
 Результат = ТестОкруглить(3.5, 0, КМеньшему, 3) И Результат;
 Результат = ТестОкруглить(-2.5, 0, КМеньшему, -3) И Результат;
 Результат = ТестОкруглить(-3.5, 0, КМеньшему, -4) И Результат;
 Результат = ТестОкруглить(0.450, 1, КМеньшему, 0.4) И Результат;
 Результат = ТестОкруглить(0.451, 1, КМеньшему, 0.4) И Результат;
 Результат = ТестОкруглить(-0.449, 1, КМеньшему, -0.5) И Результат;
 Результат = ТестОкруглить(-0.450, 1, КМеньшему, -0.5) И Результат;
 Результат = ТестОкруглить(-0.451, 1, КМеньшему, -0.5) И Результат;
 Результат = ТестОкруглить(0.1, 0, КМеньшему, 0) И Результат;
 Результат = ТестОкруглить(0.6, 0, КМеньшему, 0) И Результат;
 Результат = ТестОкруглить(1, 0, КМеньшему, 1) И Результат;

Результат = ТестОкруглить(0, 0, КБольшемуПоМодулю, 0) И Результат;
 Результат = ТестОкруглить(2.5, 0, КБольшемуПоМодулю, 3) И Результат;
 Результат = ТестОкруглить(3.5, 0, КБольшемуПоМодулю, 4) И Результат;
 Результат = ТестОкруглить(-2.5, 0, КБольшемуПоМодулю, -3) И Результат;
 Результат = ТестОкруглить(-3.5, 0, КБольшемуПоМодулю, -4) И Результат;
 Результат = ТестОкруглить(0.450, 1, КБольшемуПоМодулю, 0.5) И Результат;
 Результат = ТестОкруглить(0.451, 1, КБольшемуПоМодулю, 0.5) И Результат;
 Результат = ТестОкруглить(-0.449, 1, КБольшемуПоМодулю, -0.5) И Результат;
 Результат = ТестОкруглить(-0.450, 1, КБольшемуПоМодулю, -0.5) И Результат;
 Результат = ТестОкруглить(-0.451, 1, КБольшемуПоМодулю, -0.5) И Результат;
 Результат = ТестОкруглить(0.1, 0, КБольшемуПоМодулю, 1) И Результат;
 Результат = ТестОкруглить(0.6, 0, КБольшемуПоМодулю, 1) И Результат;
 Результат = ТестОкруглить(1, 0, КБольшемуПоМодулю, 1) И Результат;

Результат = ТестОкруглить(0, 0, КБольшему, 0) И Результат;
 Результат = ТестОкруглить(2.5, 0, КБольшему, 3) И Результат;
 Результат = ТестОкруглить(3.5, 0, КБольшему, 4) И Результат;
 Результат = ТестОкруглить(-2.5, 0, КБольшему, -2) И Результат;
 Результат = ТестОкруглить(-3.5, 0, КБольшему, -3) И Результат;
 Результат = ТестОкруглить(0.450, 1, КБольшему, 0.5) И Результат;
 Результат = ТестОкруглить(0.451, 1, КБольшему, 0.5) И Результат;
 Результат = ТестОкруглить(-0.449, 1, КБольшему, -0.4) И Результат;
 Результат = ТестОкруглить(-0.450, 1, КБольшему, -0.4) И Результат;
 Результат = ТестОкруглить(-0.451, 1, КБольшему, -0.4) И Результат;
 Результат = ТестОкруглить(0.1, 0, КБольшему, 1) И Результат;
 Результат = ТестОкруглить(0.6, 0, КБольшему, 1) И Результат;
 Результат = ТестОкруглить(1, 0, КБольшему, 1) И Результат;

Если Результат Тогда
  Сообщить("Тесты пройдены без ошибок.");
 Иначе
  Сообщить("Есть ошибки!");
 КонецЕсли;
КонецПроцедуры

Функция ТестОкруглить(Число, ДесятичныхЗнаков, МетодОкругления, ОжидаемыйРезультат)
 Перем Результат;

Результат = (ОжидаемыйРезультат = Округлить(Число, ДесятичныхЗнаков, МетодОкругления));

Сообщить("" + Число + ",  " + ДесятичныхЗнаков + ",  " + МетодОкругления + ",  " + ОжидаемыйРезультат  + ",  " + Результат);

Возврат Результат;
КонецФункции

Previous post Next post
Up