|
Функция Банковское округление | ☑ | ||
---|---|---|---|---|
0
alex44ru
31.10.18
✎
14:27
|
Недавно озадачили получать число банковским округлением. На скорую руку родил функцию.
Функция ПолучитьБанковскоеОкругление(Число, Разрядность)Экспорт Число = Формат(Число,"ЧГ=0"); СтрокаЧисел = ""; Для Индекс = 1 По СтрДлина(Число) Цикл Символ = Сред(Число, Индекс, 1); Если КодСимвола(Символ) = 44 Тогда Для Сч = 0 По Разрядность Цикл Символ = Сред(Число, Индекс, 1); СтрокаЧисел = СтрокаЧисел + Символ; Индекс = Индекс + 1; КонецЦикла; Если Число(Символ)%2 Тогда Возврат Окр(Число(Число), Разрядность, РежимОкругления.Окр15как20); КонецЕсли; СледСивол = Сред(Число, Индекс, 1); Если КодСимвола(СледСивол) <= 53 Тогда Возврат Число(СтрокаЧисел); Иначе Возврат Окр(Число(Число), Разрядность, РежимОкругления.Окр15как20); КонецЕсли; Иначе СтрокаЧисел = СтрокаЧисел + Символ; КонецЕсли; КонецЦикла; КонецФункции Просто оставлю это здесь, может кому то сбережет время. За критику буду благодарен. |
|||
2
Fragster
гуру
31.10.18
✎
14:30
|
Функция ПолучитьБанковскоеОкругление(Число, Разрядность)Экспорт
Возврат Окр(Число/2,Разрядность)*2 КонецФункции |
|||
3
Fragster
гуру
31.10.18
✎
14:31
|
воспользовался википедией:
Банковское округление (англ. banker's rounding) — округление для этого случая происходит к ближайшему чётному, то есть 2,5 → 2; 3,5 → 4. |
|||
4
1Сергей
31.10.18
✎
14:31
|
//Если КодСимвола(СледСивол) <= 53 Тогда
Если СледСивол <= "5" Тогда |
|||
5
Fragster
гуру
31.10.18
✎
14:32
|
а, понял
|
|||
6
Hans
31.10.18
✎
14:33
|
По тру кодингу "Возврат" должен быть только в конце?
|
|||
7
alex44ru
31.10.18
✎
14:36
|
(2) блин а чего так можно что ли было )))
вот это я путём не тем пошел ну да и ладно, другие не заблудятся спасибо Ваше решение намного оптимальнее моего |
|||
8
Базис
naïve
31.10.18
✎
14:36
|
(3) А я думал, что в случайный момент сумма обнуляется.
(6) Нет, это нарушает эффективность и добавляет код. |
|||
9
alex44ru
31.10.18
✎
14:42
|
(2) как Вы так слёту решили это, Вы знали?
|
|||
10
Fragster
гуру
31.10.18
✎
14:42
|
Возврат Окр(Число, Разрядность, ?(Число / Pow(10, -разрядность) % 2 < 1, РежимОкругления.Окр15как10, РежимОкругления.Окр15как20))
|
|||
11
Fragster
гуру
31.10.18
✎
14:42
|
(9) в (2) неправильно, я определение неправильно прочитал. в (10) правильно
|
|||
12
Fragster
гуру
31.10.18
✎
14:43
|
протестировал для
Число = 3.5; Разрядность = 0; Число = 2.5; Разрядность = 0; Число = 2.505; Разрядность = 2; Число = 2.515; Разрядность = 2; |
|||
13
alex44ru
31.10.18
✎
14:44
|
(10) я уже запутался
|
|||
14
Вафель
31.10.18
✎
14:45
|
банквоское - это
1.53 =2 1.52 = 1 так? |
|||
15
Fragster
гуру
31.10.18
✎
14:46
|
(14) я понял,что банковское, это 2.5 -> 2, 3.5 -> 4
|
|||
16
Fragster
гуру
31.10.18
✎
14:48
|
единственное, может быть для отрицательных чисел нужно поправить. в любом случае вот как раз для этого нужно юнит тестирование и с ним будет прям просто.
|
|||
17
Вафель
31.10.18
✎
14:48
|
РежимОкругления.Окр15как10 - это не то самое?
|
|||
18
Fragster
гуру
31.10.18
✎
14:48
|
(17) нет, так 3.5 будет 3
|
|||
19
Fragster
гуру
31.10.18
✎
14:48
|
собственно, см. 10, там правильно
|
|||
20
Злопчинский
31.10.18
✎
14:54
|
Банковское - это когда по четным дням округляют в большую сторону, а по нечетным дням округляют в меньшую..
|
|||
21
alex44ru
31.10.18
✎
14:59
|
у меня в задании было написано так:
Округление суммы осуществляется по результату умножения (применяется округление к ближайшему четному (банковское) - округляется до 2-го знака в зависимости от 3-го знака. Например, число 0,785 округляется до 0,78) |
|||
22
Fragster
гуру
31.10.18
✎
15:01
|
ну в общем в (10) правильно все, а те, кто определение (21) писал - чудаки
|
|||
23
Fragster
гуру
31.10.18
✎
15:02
|
больше бы тесткейсов набросали, все было бы понятно
|
|||
24
Fragster
гуру
31.10.18
✎
15:02
|
что 0,775 до 0,78, а 0,765 - до 0,76
|
|||
25
alex44ru
31.10.18
✎
15:03
|
(22) чудаки чудаками, но я вынужден подстраиваться под них
|
|||
26
Fragster
гуру
31.10.18
✎
15:04
|
(25) ну вот за (10) мне как-нибудь проставишься
|
|||
27
alex44ru
31.10.18
✎
15:05
|
(26) физмат закончил? у меня только один взгляд на эту функцию вызывает взрыв мозга
|
|||
28
Fragster
гуру
31.10.18
✎
15:06
|
(27) компьютерных технологий и управления. на самом деле если писать не в одну строку, то понятнее.
|
|||
29
Fragster
гуру
31.10.18
✎
15:07
|
кстати, Число / Pow(10, -разрядность) % 2 можно заменить на Число * Pow(10, разрядность) % 2
|
|||
30
alex44ru
31.10.18
✎
15:10
|
(29) только что ткнули носом
есть сумма 20 827,52 её надо умножить на коэф 1.03 получим 21452,3456 после округления должно стать 21452,34 а по твоей формуле (10) получается 21452,35 а вот по формуле (2) норм |
|||
31
Дмитрий
31.10.18
✎
15:11
|
Банковское это если пеня за просроченный кредит - округляют в большую сторону, а если процент по депозиту - в меньшую )
|
|||
32
Fragster
гуру
31.10.18
✎
15:13
|
(30) нет. 21452,345 должно стать 21452,34 - оно и становится. а 21452,3456 должно стать 21452,35
|
|||
33
Fragster
гуру
31.10.18
✎
15:13
|
если хочется, чтобы получилось 21452,34 предварительно нужно получить с точностью на 1 знак больше
|
|||
34
alex44ru
31.10.18
✎
15:14
|
(32) я все понимаю но у меня в задании так (21)
|
|||
35
Fragster
гуру
31.10.18
✎
15:14
|
например Цел(Число * Pow(10, разрядность+1)) / Pow(10, разрядность)
|
|||
36
Fragster
гуру
31.10.18
✎
15:16
|
в одной строке:
Результат = Окр(Цел(Число * Pow(10, разрядность + 1)) / Pow(10, разрядность + 1), Разрядность, ?(Число * Pow(10, разрядность) % 2 < 1, РежимОкругления.Окр15как10, РежимОкругления.Окр15как20)); |
|||
37
Fragster
гуру
31.10.18
✎
15:16
|
вот для этого и нужно юнит тестирование, повторюсь
|
|||
38
alex44ru
31.10.18
✎
15:17
|
(37) оставлю тогда пока как у меня, пусть страшно смотрится, зато считает как требуют
|
|||
39
Fragster
гуру
31.10.18
✎
15:18
|
(38) ну, если требования формализовать нормально, то все будет считать правильно, да и проверить можно.
|
|||
40
Fragster
гуру
31.10.18
✎
15:18
|
пока ошибки в (36) с учетом (30) нет
|
|||
41
Fragster
гуру
31.10.18
✎
15:18
|
тесты пройдены
|
|||
42
Fragster
гуру
31.10.18
✎
15:19
|
все, что были до этого + случай из (30)
|
|||
43
alex44ru
31.10.18
✎
15:20
|
(42) как ты это делаешь ))), тебе бы конфигурации прикладные в 1С писать
|
|||
44
Fragster
гуру
31.10.18
✎
15:22
|
в 4 строки:
ОбрезанноеЧисло = Цел(Число * Pow(10, разрядность + 1)) / Pow(10, разрядность + 1); ЧислоДляРежимаОкругления = Число * Pow(10, разрядность); НужныйРежимОкругления = ?(ЧислоДляРежимаОкругления % 2 < 1, РежимОкругления.Окр15как10, РежимОкругления.Окр15как20); Возврат Окр(ОбрезанноеЧисло, Разрядность, НужныйРежимОкругления); |
|||
45
Fragster
гуру
31.10.18
✎
15:30
|
Кстати, ЧислоДляРежимаОкругления возможно нужно тоже получать из ОбрезанноеЧисло, а не из Число
|
|||
46
alex44ru
31.10.18
✎
15:35
|
(45) я уже давно запутался и не понимаю написанного тут, но тебе верю, расчёты показывают, что алгоритм считает как надо, но будем проверять
|
|||
47
Fragster
гуру
31.10.18
✎
15:37
|
(46) лично я запутался в (0) да и работать с числами как со строками ИМХО странно
|
|||
48
alex44ru
31.10.18
✎
15:38
|
(47) в итоге сделал так:
ОбрезанноеЧисло = Цел(Число * Pow(10, разрядность + 1)) / Pow(10, разрядность + 1); ЧислоДляРежимаОкругления = ОбрезанноеЧисло * Pow(10, разрядность); НужныйРежимОкругления = ?(ЧислоДляРежимаОкругления % 2 < 1, РежимОкругления.Окр15как10, РежимОкругления.Окр15как20); Возврат Окр(ОбрезанноеЧисло, Разрядность, НужныйРежимОкругления); |
|||
49
alex44ru
31.10.18
✎
15:40
|
(47) я тяжело работаю с различными функциями над числами, видать мой мозг как у программера сложился в юности, когда я программировал для Z80 прямо в ассемблере, там функций работы над числами не было, в основном сложение, вычитание и бинарные
|
|||
50
PR
31.10.18
✎
15:41
|
(10) Я бы написал так
|
|||
51
Fragster
гуру
31.10.18
✎
15:42
|
(50) а зачем тут первая ветка? ну и (30) добавляет нюанс
|
|||
52
Fragster
гуру
31.10.18
✎
15:42
|
а зачем тут первая ветка Если?
|
|||
53
PR
31.10.18
✎
15:48
|
(51) Если число не пограничное, то есть, например, не 1.5, то пофиг как округлять
|
|||
54
PR
31.10.18
✎
15:50
|
(51) В (30) не нюанс, а бред сивой кобылы какой-то, 21452,3456 с округлением до двух знаков — это не пограничное число, с какого рожна после округления должно стать 21452,34, а не 21452,35, спрашивается?
|
|||
55
Fragster
гуру
31.10.18
✎
15:50
|
(53) вот именно. по этому эту проверку можно вообще убрать и оставить только то, что в Иначе
|
|||
56
PR
31.10.18
✎
15:51
|
(55) Охренеть. И чему тогда будет равно РежимОкругленияЧисла?
|
|||
57
Fragster
гуру
31.10.18
✎
15:52
|
ну и
ПоловинаОкругленногоЧисла = Окр(Число, Разрядность, РежимОкругления.Окр15как10) / 2; Если ПоловинаОкругленногоЧисла = Окр(ПоловинаОкругленногоЧисла, Разрядность, РежимОкругления.Окр15как10) Тогда реально эквивалентно ЧислоДляРежимаОкругления % 2 < 1 только у меня короче |
|||
58
Fragster
гуру
31.10.18
✎
15:52
|
(56)
Если ПоловинаОкругленногоЧисла = Окр(ПоловинаОкругленногоЧисла, Разрядность, РежимОкругления.Окр15как10) Тогда РежимОкругленияЧисла = РежимОкругления.Окр15как10; Иначе РежимОкругленияЧисла = РежимОкругления.Окр15как20; КонецЕсли; |
|||
59
Fragster
гуру
31.10.18
✎
15:52
|
чему-то да будет равно, но поскольку пофиг - то пофиг
|
|||
60
PR
31.10.18
✎
15:56
|
(57) Никогда не любил укорачивателей, читай сишников
Напишут строчку в 60 символов, в которой расчет суммы документа зашифрован, никуя непонятно, хрен уже что исправишь, чтобы разобраться в смысле, надо месяц расшифровывать в человеческий вид, зато автор ходит гоголем, аж рубашка на груди трещит |
|||
61
Fragster
гуру
31.10.18
✎
15:57
|
(60) ну если для тебя функция остатка от деления сложна, то пора начинать думать о карьере менеджера, а не программиста
|
|||
62
PR
31.10.18
✎
15:58
|
(58) А, ви в етом смисле
Ну наверное да, лень думать |
|||
63
Fragster
гуру
31.10.18
✎
15:58
|
или оператор ?(,,)
|
|||
64
Fragster
гуру
31.10.18
✎
15:58
|
(62) > лень думать
все беды от этого, и (60) тоже |
|||
65
PR
31.10.18
✎
15:59
|
(61) Функция остатка от деления оперирует предварительно рассчитанным числом
Так-то и в C все просто, 255 символов и все, епта, но реально 60 символов можно неделю расшифровывать |
|||
66
PR
31.10.18
✎
16:01
|
(64) Мой код читабельнее, его легче проверить и его легче отлаживать
Практически всегда эти аргументы важнее, чем экономия места на винчестере |
|||
67
Fragster
гуру
31.10.18
✎
16:02
|
(65) ну на самом деле понять, что ты имеешь ввиду под сравниванием половины округленного числа с его же округлением сложно. а проверка на самом деле та же - что число лежит в диапазоне четное +-1
|
|||
68
Fragster
гуру
31.10.18
✎
16:02
|
(66) не уверен
|
|||
69
Fragster
гуру
31.10.18
✎
16:03
|
(10) и (36) да, повыпендриваться. а (48) уже норм, можно комментарий добавить, конечно.
|
|||
70
PR
31.10.18
✎
16:04
|
(67) Поэтому сначала я хотел написать что-то типа "ЭтоПограниченоеЧисло = ..." и "ЭтоЧетноеЧисло = ...", так и надо было сделать :))
|
|||
71
PR
31.10.18
✎
16:04
|
+(70) Пограничное конечно же
|
|||
72
PR
31.10.18
✎
16:11
|
(68) В чем не уверен?
Что чем ниже сложность кода, тем он читабельнее? Или что чем ниже сложность кода, тем его легче проверить? Или что чем меньше операторов в одной строке кода, тем легче отлаживать код? |
|||
73
PR
31.10.18
✎
16:12
|
(69) С этим да, соглашусь, (48) уже терпимо, с комментариями вообще зайдет нормально
|
|||
74
Fragster
гуру
31.10.18
✎
16:13
|
(71) достаточно нарисовать условие в мат. терминах:
(2n+1 -0.5, 2n+1 + 0.5) -> 2n+1 [2n - 0.5, 2n + 0.5] -> 2n и все становится просто. + некоторый нюанс из (30) |
|||
75
ReaLg
31.10.18
✎
16:13
|
Я правильно понял, что 1,331 округляется до 1,34 а 1,289 до 1,28?
Тогда так можно: Число2 = ПервоначальноеЧисло * Pow(10, Разрядность); Число3 = Цел(Число2); Число4 = ?(Число3 % 2 = 0, Число3, Число3 + 1); Результат = Число4 / Pow(10, Разрядность); Только надо еще понять, правильно ли что 0,004 - это 0 и 1,291 это 1,3 |
|||
76
Fragster
гуру
31.10.18
✎
16:14
|
и именно вариант с остатком от деления для определения вида числа ближе (для меня :))
|
|||
77
PR
31.10.18
✎
16:14
|
(74) Добавляет сложности в понимание то, что округляется до n знаков, а не до 0 или до 2
|
|||
78
Fragster
гуру
31.10.18
✎
16:14
|
(75) неправильно
|
|||
79
Tonik992
31.10.18
✎
16:14
|
(6) В большинстве случаев - да. Я за такой код.
(8) Не могу понять, почему нарушает эффективность? Что значит эффективность по отношению местонахождения "Возврат" ? |
|||
80
Вафель
31.10.18
✎
16:14
|
(75) вроде только цифра 5 округляется по разному
|
|||
81
Fragster
гуру
31.10.18
✎
16:15
|
(77) этим в данном случае можно пренебречь. собственно, в ОКР это добавили чисто для удобства, в ЦЕЛ - забили.
|
|||
82
Fragster
гуру
31.10.18
✎
16:16
|
(81) дать правильное определение n, не целое число, а целое, поделенное на 10 в степени разрядность
|
|||
83
ReaLg
31.10.18
✎
16:17
|
(80) В (21) написано к ближайшему четному. Про цифру 5 ничего нет. Для 2.331 ближайшее четное (во втором знаке после запятой) это 2.34 :))
|
|||
84
PR
31.10.18
✎
16:18
|
(75) Хм, что-то я по ходу неправильно свой вариант написал, надо еще раз прочитать про банковское округление
Интересно, в чем смысл округления до ближайшего целого? |
|||
85
Fragster
гуру
31.10.18
✎
16:18
|
(83) правильно, надо у заказчиков требовать тест кейсы
|
|||
86
PR
31.10.18
✎
16:19
|
+(84) До ближайшего четного в смысле
|
|||
87
ReaLg
31.10.18
✎
16:20
|
(85) Ну я поэтому и заинтересовался - что по (21) я понял задачу не так, как ее в топике решают :))
|
|||
88
Fragster
гуру
31.10.18
✎
16:22
|
(83) до ближайшего четного в (2)
|
|||
89
PR
31.10.18
✎
16:30
|
Короче, ТС нихрена не написал, что такое сабж
http://stan-1.ru/bankovskoe-okruglenie-okazyvaetsya-est-i-takoe/ |
|||
90
PR
31.10.18
✎
16:38
|
+(89) Мда, эта статейка тоже по ходу не эталон
Нужно определение банковского округления Исходя из здравого смысла люди хотели для сокращения накопленных округлений спорных чисел округлять их четные влево, нечетные вправо |
|||
91
PR
31.10.18
✎
16:45
|
То есть для округления до двух знаков:
- Все числа с дробной частью "ab5", где b четное, округляются по правилу РежимОкругления.Окр15как10 - Все числа с дробной частью "ab5", где b нечетное, округляются по правилу РежимОкругления.Окр15как20 — Все остальные числа округляются как угодно (результат будет одинаковым), пусть хоть по правилу РежимОкругления.Окр15как10 Тогда я вроде как верно написал :)) |
|||
92
PR
31.10.18
✎
16:51
|
+(91) На всякий случай, числа "123.125001", "123.124999" и "123.125500" попадают в прочее
|
|||
93
Вафель
31.10.18
✎
16:52
|
так вроде для округления до 2х знаков
123.125001 == 123.125 |
|||
94
PR
31.10.18
✎
16:57
|
(93) 123.125001 не является спорным, оно без вариантов округляется вверх до 123.13
|
|||
95
bolobol
31.10.18
✎
16:59
|
(94) И, конечно же - 3 - это самое чётное из всех
|
|||
96
Вафель
31.10.18
✎
17:00
|
(94) Эх Рома-Рома, такую простую задачу не осилил
|
|||
97
PR
31.10.18
✎
17:03
|
+(94) Спорным для округления до двух знаков является число, где округляемый остаток равен ровно 0.005, когда непонятно, то ли вторую цифру после запятой увеличивать на 1 то ли нет
То есть в 123.125001 округляемый остаток равен 0.005001, а это больше, чем 0.005, значит нужно увеличивать, получится 123.13 |
|||
98
PR
31.10.18
✎
17:03
|
(95) Рукалицо
Напиши определение банковского округления |
|||
99
PR
31.10.18
✎
17:04
|
(96) Смехуёчки в строю
|
|||
100
bolobol
31.10.18
✎
17:08
|
(98) Повторить, штолле? Самому не осилить вики и в 100 постах не найти цитату определения?
|
|||
101
PR
31.10.18
✎
17:23
|
(100) Ну повтори, если видишь _определение_, а я не вижу
Или не выеживайся |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |