Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.09.04;
Скачать: CL | DM;

Вниз

Округление чисел. Неужели ТАК правильно???   Найти похожие ветки 

 
Calm ©   (2003-08-13 10:31) [0]

Вчера услышал от преподавателя курсов Бух. учета следующее правило округления:
1. 15.746 -> 17.7
2. 15.764 -> 17.8
3. 17.752 -> 17.8
4. 17.252 -> 17.2
5. 17.052 -> 17.0

Было выдано утверждение - Если за последней значащей цифрой стоит 5, то последнюю цифру увеличивают, если она нечетная и уменьшют, если четная.

Первый раз слышу о таком? Четная цифра, нечетная... Неужели я когда-то прогулял какую-то лекцию по вычислительной математике? Мы там много разных округлений изучали, но чтобы такого...
Да и в школе не было такого!

Неужели такое приавло действительно существует???


 
Е-Моё имя ©   (2003-08-13 10:35) [1]

ты окончательно упал в моих глазах
;))))))


 
Внук ©   (2003-08-13 10:37) [2]

Это так называемое "бухгалтерское" округление. Имеет место быть.


 
Anatoly Podgoretsky ©   (2003-08-13 10:42) [3]

4. 17.252 -> 17.2
Это не верно, но всегда можно ввести в рамки закона
Эти правило действуют когда лежит ровно посредине, наприме
3. 17.750 -> 17.8
4. 17.250 -> 17.2


 
Calm ©   (2003-08-13 10:47) [4]


> Эти правило действуют когда лежит ровно посредине, наприме
>

Но в курсе вышки, выч. мата и около математических науках такого утверждения я не встречал. Я закончил спец. программное обеспечение выч. техники и на малое количество часов математики мы пожаловаться не могли. Я твердо был уверен, что если за последней значащей цифрой стоит 5, то округляется в большую сторону. Даже если ровно посередине (17,250000).
Я не прав?


> Это так называемое "бухгалтерское" округление. Имеет место
> быть.

Это шутка, или серьезно? Если серьезно, то это должно быть прописано в каком-то нормативном документе. В каком?


 
Внук ©   (2003-08-13 10:51) [5]

>>Это шутка, или серьезно?
Вполне серьезно. То, к чему мы с тобой привыкли - обычное математическое округление. А в бухгалтерских расчетах применяется то, о чем ты пишешь. И в программах соответствующих. А насчет нормативных документов не знаю, я ж не "букгактер".


 
Anatoly Podgoretsky ©   (2003-08-13 10:51) [6]

Calm © (13.08.03 10:47) [4]
В какой то мере прав, существует много методов округления, нормативные документы есть, много, разные. Это внутреннее дело. Сейчас в основном применяют так называемое "банковское" округление, поскольу оно дает меньшую погрешность на массиве чисел.


 
sniknik ©   (2003-08-13 10:52) [7]

> Неужели такое приавло действительно существует???
а ты попробуй в дельфях округлить там такое и получиш

RoundTo uses “Banker’s Rounding” to determine how to round values ....

The following examples illustrate the use of RoundTo:
Expression Value
RoundTo(1234567, 3) 1234000
RoundTo(1.234, -2) 1.23
RoundTo(1.235, -2) 1.24
RoundTo(1.245, -2) 1.24


 
Nikolay M. ©   (2003-08-13 10:53) [8]


> Это так называемое "бухгалтерское" округление.

Есть, стопудово.
Не знаю точной подоплеки, но, возможно, при частой работе такого округления при больших посчетах округления вверх-вниз компенсируют друг друга (их будет примерно поровну) и получается золотая середина :)


 
Calm ©   (2003-08-13 10:54) [9]


> Это внутреннее дело

Внутренее дело кого? Организации или отрасли?

Если я в своей организации буду применять одно округление, а налоговая другое, то на массиве чисел будет разногласие. Небольшое разногласие, но формально с точки зрения налоговой я окажусь не прав? Штрафы, пеня...


 
Calm ©   (2003-08-13 11:00) [10]

ну дела...


 
Толик ©   (2003-08-13 11:04) [11]

Подобное округление принято в бухучете. Соотв., налоговая тоже применяет это округление, так что всё должно сойтись, по крайней мере на бумаге :))


 
DiamondShark ©   (2003-08-13 11:20) [12]

Ох-хо-хо... Ещё раз.
Предположим, что распределение чисел у нас близко к равномерному случайному. Тогда при "арифметическом" округлении имеем:

Цифра Погрешность
0 0
1 -1
2 -2
3 -3
4 -4
5 +5
6 +4
7 +3
8 +2
9 +1

Как легко заметить, если имеется большой массив чисел, которые потом понадобится суммировать (итого для позиций документа, сальдо по счёту и т.п.), то при "арифметическом" округлении будет накапливаться систематическая погрешность с матожиданием
0.5*10^n * 0.1 * N
где:
n -- десятичный вес разряда, до которого производится округление (до двух знаков n=-2, до целых n=0 и т.д.)
0.1 -- вероятность каждой цифры
N -- число суммируемых чисел в массиве

Для того, чтобы выровнять вероятности погрешностей надо скомпенсировать единственную нескомпенсированную (см. таблицу выше) погрешность +5. Для этого она искусственно разбивается на две равновероятные +5 -5 в зависимости от чётности предыдущей цифры.

Кстати, в слове состояния FPU есть флажок, контролирующий режим округления (арифметический/бухгалтерский).


 
Anatoly Podgoretsky ©   (2003-08-13 11:42) [13]

Calm © (13.08.03 10:54) [9]
Внутреннее дело двух сторон, они должны действовать по едниным правилам, по каким не важно


 
uw ©   (2003-08-13 12:11) [14]

При арифметических вычислениях дело не заканчивается тем разрядом, который мы округляем. При равномерном случайном распределении за цифрой 0 идет в среднем 0.5. Поэтому:

0 -0.5
1 -1.5
2 -2.5
3 -3.5
4 -4.5
5 +4.5
6 +3.5
7 +2.5
8 +1.5
9 +0.5

Если мы это все просуммируем, то получим как раз 0.


 
Dimka Maslov ©   (2003-08-13 12:14) [15]

На самом деле такое окгугление правильнее, если потом придётся суммировать резльтаты окргуления, если действовать общепринятым способом (округлять в большую сторону если последняя цифра 5) даст большую погрешность в сумме чисел. Для минимизации погрешности суммы и применяется такое вот округление. Оно используется не только в бухгалтерских расчётах, но и напрмер в геодезических при обработке результатов инструментальной съёмки.


 
uw ©   (2003-08-13 12:26) [16]

>Dimka Maslov © (13.08.03 12:14) [15]

Как это может быть? Отрезок от 0 до 5-d в точности равен отрезку от 5 до 10-d, где d определяется разрядностью машины. Сдается мне, что рассматриваемый хитрый алгоритм - предрассудок бухгалтеров-троечников.


 
Dimka Maslov ©   (2003-08-13 12:36) [17]

>uw
Вероятность того, что перед пятёркой окажется чётное или нечётное число примерно одинаковая. Если же всё время округлять в большую сторону, набегающая погрешность будет только увеличиваться, а при таком подходе, погешность будет то складываться, то вычитаться, что в итоге должно её минимизировать. А если это не делать, то это черевать либо финансовыми потерями, либо невозможностью нормальной эксплуатации или вообще обрушением строящегося сооружения. А рассматриваемы хитрый аглоритм это не предрассудок бухгалтеров троечников, а методика, предложенная для статистических рассчётов самим Гауссом (если тебе это имя о чём-то говорит)


 
uw ©   (2003-08-13 12:41) [18]

>Dimka Maslov © (13.08.03 12:36) [17]

Ты меня Гауссом не пугай. Ты мне пальцем покажи, где ошибка в посте uw © (13.08.03 12:11) [14], и я скажу тебе спасибо.


 
nikkie ©   (2003-08-13 12:41) [19]

>uw
ты рассуждаешь как математик. а у бухгалтеров все числа имеют конечное число знаков. если отбрасывается 1 цифра, то DS дал тебе табличку. если отбрасывается 2 цифры, то погрешность получается ближе к твоей, но все же не 0.5, а 0.45 = (сумма от 0 до 9)/10. поэтому при суммировании будет средняя погрешность будет ненулевой. чем больше знаков было в исходных числах, тем меньше эта погрешность, но никогда не ноль. бухгалтерское правило делает ее нулем при любом количестве отбрасываемых цифр.


 
uw ©   (2003-08-13 12:49) [20]

>nikkie © (13.08.03 12:41) [19]

Я не понимаю, от чего отбрасывается. Предположим, мы взвесили колбасу, посчитали, получили 32.1234567... руб. Округляем. Вместо истинного значения с периодом получаем 32.12 руб. И что?


 
nikkie ©   (2003-08-13 13:00) [21]

... - не получается никак.
цена колбасы - 2 знака после запятой.
весы - 4 знака после запятой.
итого - 6, округляем до 2-х.
сделай оценку погрешнсти в такой ситуации.


 
nikkie ©   (2003-08-13 13:01) [22]

сорри, весы - 3 знака. итого - 5.


 
uw ©   (2003-08-13 13:06) [23]

>Dimka Maslov © (13.08.03 12:36) [17]
>Если же всё время округлять в большую сторону, набегающая погрешность будет только увеличиваться.

Школьный алгоритм округления не все время округляет в большую сторону. Цифры 0,1,2,3,4 он округляет в меньшую сторону, а цифры 5,6,7,8,9 - в большую. И тех, и других ровно по пять. Если у Гаусса другие соображения, покажи мне их, я не нашел в Интернете.


 
Dimka Maslov ©   (2003-08-13 13:06) [24]

>uw
Пример:
1.245 + 1.115 = 2.36

Округляем до двух знаков в большую сторону, поскольку последняя цифра 5 получаем:
1.25 + 1.12 = 2.3 7 (имеем погрешность при суммировании)

А теперь округляем по Гауссу:
1.24 + 1.12 = 2.36 (погрешности нет)


 
uw ©   (2003-08-13 13:18) [25]

Пример:

1.244 + 1.245 = 2.489 = 2.49

По-школьному:
1.24 + 1.25 = 2.49

По Гауссу:
1.24 + 1.24 = 2.48


 
DiamondShark ©   (2003-08-13 14:57) [26]


> uw © (13.08.03 13:06) [23]


А вот и ошибка.


Цифры 0,1,2,3,4 он округляет в меньшую сторону, а цифры 5,6,7,8,9 - в большую


Цифра 0 вообще никуда не округляется.

Решите примерчик
1.25 + 1.35 + 1.45 + 1.55 = ?

а) точно
б) округляя каждое слагаемое до #.# арифметически
б) округляя каждое слагаемое до #.# по-бухгалтерски

Сравните ответы и сделайте вывод.


 
app ©   (2003-08-13 14:59) [27]

DiamondShark © (13.08.03 14:57) [26]
влево 4, вправо 5, а распределение нормально


 
uw ©   (2003-08-13 15:29) [28]

>DiamondShark © (13.08.03 14:57) [26]

Округляем 0 в меньшую сторону, почитай uw © (13.08.03 12:11) [14].

Контрпримерчик я уже приводил (uw © (13.08.03 13:18) [25] ).

Но я еще и помоделировал и увидел, что по-школьному ничуть не хуже:

procedure Test;
var
a, b: Double;
s1, s2: Double;
i: Integer;
begin
s1 := 0; s2 := 0;
Randomize;
a := RoundTo(1.235, -2);
a := RoundTo(1.245, -2);
a := RoundTo(1.255, -2);
a := RoundTo(1.265, -2);
for i := 1 to 1000 do begin
a := Random(10000) / 1000;
b := Random(10000) / 1000;
s1 := s1 + Round((a + b) * 1000) / 1000 -
(Round(a * 100) / 100 + Round(b * 100) / 100);
s2 := s2 + Round((a + b) * 1000) / 1000 - (RoundTo(a, -2) + RoundTo(b, -2));
end;
end;


 
nikkie ©   (2003-08-13 17:22) [29]

>uw
похоже еще один самолет ;) но с математикой я думаю проще будет разобраться.

давай для простоты рассмотрим арифметическое округление десятичного числа с n знаками после запятой до целого. берем ну очень равномерное распределение распределение, все числа от 0 до 0,99..99:
0,00...00
0,00...01
0,00...02
0,00...03
...
0,49...99 - округляются до 0
0,50...00
0,50...01
...
0,99...99 - округляются до 1

легко видеть, что средняя ошибка округления 5 * 10^(-n)


 
DiamondShark ©   (2003-08-13 17:38) [30]


> uw © (13.08.03 15:29) [28]

Зачем быть таким упёртым?


> Округляем 0 в меньшую сторону, почитай uw © (13.08.03
> 12:11) [14].

1.20 округляем до одного знака, сколько получим?


> Но я еще и помоделировал и увидел, что по-школьному ничуть
> не хуже:

Ерунду вы намоделировали.

program Project1;
{$APPTYPE CONSOLE}

var
Table: array[word] of double;
i: integer;
S, S1, S2: extended;
begin
randomize;
S := 0;
for i := low(Table) to high(Table) do
begin
Table[i] := Random * 10;
S := S + Table[i]; // это будет точная сумма
end;

Set8087CW($1372); // включаем "бухгалтерское" округление
S1 := 0;
for i := low(Table) to high(Table) do
S1 := S1 + Round(Table[i]);

Set8087CW($1B72); // включаем "школьное" округление
S2 := 0;
for i := low(Table) to high(Table) do
S2 := S2 + Round(Table[i]);

writeln(S:20:0, S1:20:0, S2:20:0);
if S2 <= S1 then writeln("DS должен мне $1000 !!!");

readln;
end.


Запускаем, наслаждаемся набежавшей погрешностью.
Можете тело программы заключить в бесконечный цикл, ответ сюда пишите не раньше, чем заработаете $1000.


 
uw ©   (2003-08-14 11:19) [31]

>nikkie © (13.08.03 17:22) [29]

Не очень понял, к чему ты это привел, но это уже и неважно. На самом деле, я твою мысль понял уже после разговора о колбасе. Да и мой контрпример Dimka Maslov © указывал на то, что не все симметрично. Но, с другой стороны, я был убежден в симметричности Round. С DS разговаривать трудно: ты ему говоришь, что округление числа 1.209999 до первого десятичного знака происходит в меньшую сторону, а он делает вид, что округления бывают только с последними цифрами и приводит пример 1.20 и обзывает тебя упертым ослом. Но выяснилось, что и с ним можно разговаривать, если привести пример, все равно какой. После его примера я с изумлением обнаружил, что и Round по умолчанию тоже использует «банковский» алгоритм, и я пришел к внутреннему согласию. Так что, все методы хороши – и твой, мягкий, и буйно агрессивный метод DS. Единственный метод, который здесь ни к чему не приводит – это метод ссылки на имя Остроградского или даже Гаусса: они ничего не знали про реализацию Round.


 
nikkie ©   (2003-08-14 13:00) [32]

>uw
>На самом деле, я твою мысль понял уже после разговора о колбасе.
дык, если б ты об этом сказал, я бы и не встревал... ;)


 
DiamondShark ©   (2003-08-14 13:03) [33]

Представим число X в виде
X = A + a*10^(n+1) + b*10^n + R, где:
A >= 10^(n+1)
a, b in {0..9}
R < 10^n
n = ...-2, -1, 0, 1, 2... вес отбрасываемого разряда

Тогда округлённое число X" будет получено в виде
X" = A + a"*10^(n+1),
а правила округления описывают получение a".
Для "школьного" округления
a" = a при b < 5
a" = a+1 при b >=5

Погрешность
d = X - X" = (A + a*10^(n+1) + b*10^n + R) - (A + a"*10^(n+1)) = (a-a")*10^(n+1) + b*10^n + R
d = b*10^n + R при b < 5
d = -1*10^(n+1) + b*10^n + R = -1*(10-b)*10^n + R при b >= 5

Возможные диапазоны погрешностей:
b диапазон
-----------------------------
0 [0; 10^(n-1)]
1 (10^(n-1); 10^n]
2 (10^n; 2*10^n)
3 (2*10^n; 3*10^n]
4 (3*10^n; 4*10^n]
5 [-5*10^n; -4*10^n)
6 [-4*10^n; -3*10^n)
7 [-3*10^n; -2*10^n)
8 [-2^10^n; -10^n)
9 [-10^n; 0)

У кого-то ещё остались какие-то вопросы?

Специально для uw
Вопрос с округлением нуля, полагаю, решён? Диапазон погрешностей округленя девятки, как легко видеть, перекравает диапазон округления нуля и единицы. А диапазон пятёрки остаётся единственным не имеющим симметричного диапазона другого знака.
Со мной трудно разговаривать с позиций "я был глубоко убеждён", но чрезвычайно легко, как вы верно заметили, говорить доказательно.

ЗЫ
Номер сообщения, где употредляется слово "осёл", надеюсь, не составит труда указать?


 
uw ©   (2003-08-14 13:38) [34]

>DiamondShark © (14.08.03 13:03) [33]
>Номер сообщения, где употредляется слово "осёл", надеюсь, не составит труда указать?

DiamondShark © (14.08.03 13:03) [33] :)


 
Anatoly Podgoretsky ©   (2003-08-14 13:39) [35]

Удалено модератором
Примечание: Личная переписка


 
uw ©   (2003-08-14 16:04) [36]

>DiamondShark © (14.08.03 13:03) [33]

Объясни мне только одно: почему

Возможные диапазоны погрешностей:
b диапазон
-----------------------------
0 [0; 10^(n-1)]

если d = b*10^n + R при b < 5, а R < 10^n?


 
nikkie ©   (2003-08-14 16:10) [37]

>Объясни мне только одно: почему
а это чтобы ответ какой надо получить :)
если делать по правде, то получится
b диапазон
-----------------------------
0 [0; 10^n)
1 [10^n; 2*10^n)
2 [2*10^n; 3*10^n)
3 [3*10^n; 4*10^n)
4 [4*10^n; 5*10^n)
5 [-5*10^n; -4*10^n)
6 [-4*10^n; -3*10^n)
7 [-3*10^n; -2*10^n)
8 [-2^10^n; -10^n)
9 [-10^n; 0)
в среднем 0. и останутся еще вопросы... :))


 
uw ©   (2003-08-14 16:13) [38]

>nikkie © (14.08.03 16:10) [37]

Я побоялся так конкретно (:


 
DiamondShark ©   (2003-08-14 16:52) [39]


> uw © (14.08.03 16:04) [36]

Ай, как нехорошо получилось...
0 [0; 10^n)
1 [10^n; 2*10^n)
2 [210^n; 3*10^n)
3 [3*10^n; 4*10^n]
4 [4*10^n; 5*10^n]

Хуманум эраре эст. Но это уже не важно.
Елки-палки. Вы мне совсем мозги запудрили.

round(2.5) = 2
round(2.500000000000000001) = 3

"Бухгалтерское" правило применяется не просто если b=5 (в ранее введённых обозначениях), а ещё если R=0. А для случая R=0 диапазоны погрешностей вырождаются в числа, я уже эту табличку приводил:
b d
---------------------
0 +0
1 +1*10^n
2 +2*10^n
3 +3*10^n
4 +4*10^n
5 -5*10^n
6 -4*10^n
7 -3*10^n
8 -2*10^n
9 -1*10^n


 
uw ©   (2003-08-14 17:07) [40]

>DiamondShark © (14.08.03 16:52) [39]

Все ОК. Теперь мне можно идти в булгахтеры... но в маленькие :)



Страницы: 1 2 вся ветка

Текущий архив: 2003.09.04;
Скачать: CL | DM;

Наверх




Память: 0.59 MB
Время: 0.021 c
14-10897
новичёк
2003-08-04 22:53
2003.09.04
Алгоритмы распознавания образов


1-10683
Andrey V.
2003-08-13 09:00
2003.09.04
про TDateTime


3-10587
nortsov
2003-08-14 11:58
2003.09.04
удаление в firebird


14-10936
pasha_golub
2003-08-16 19:09
2003.09.04
И тут Остапа понесло...


3-10581
Fenixx
2003-08-14 15:26
2003.09.04
Импорт данных в БД из текстового файла