Страницы: 1 2 След.
RSS
округление
 
как округлить значение так чтобы не была погрешности в сумме, надо написать ROUND а потом не помню
 
????  
Вопрос исчерпывающий. Попробуйте нажать мастер функций, выбрать полный алфавитный перечень и подобрать себе нужную. Ведь при расчете зарплаты/сотруднику/ округляют до 2 знаков, пересчет валюты - 5, и не маловажно знать по какому правилу, или для чего Вам необходимо округление.  
Английский и русский вариант.  
=ROUND(A1;2) =ОКРУГЛ(A1;2)  
Округляет число до указанного количества десятичных разрядов (по правилам математики).
 
спасиба,  но что вы называите "мастер функций" может напишите англиский вариант :))
 
Есть такой знак - fx /вставка функции-, при нажатии активизируется мастер функций.
 
меню Вставка - Функция...
 
---  
Округление в Excel вполне предсказуемое, т.к. оно выполняеться по математическим правилам.  
 
Но, не всем известно, что функция Round() в VBA округляет не по математическим правилам, а по банковским.  
В частности:    
Round(1.5)=2, ничего необычного;  
Но Round(2.5)=2, а не 3, как обычно ожидается.  
 
Упрощенно, для одного десятичного знака правило банковского округления такое: половинки (0.5), прибавленные к нечетным числам округляются до целых с избытком, а к четным - с недостатком.  
Смысл - в уменьшении систематической ошибки округления при суммировании большого количества чисел. Это удобно банкам, но знают ли об этом их клиенты?  
 
' Проверка VBA- округления  
Sub Нюансы_округления()  
MsgBox "Round(1.5)=" & Round(1.5) & vbCr _  
& "Round(2.5)=" & Round(2.5), _  
vbExclamation, "Crazy VBA round"  
End Sub  
 
Интересно, что многие публикации ошибаются относительно математического метода округления в VBA, и даже коммерческие программы порой используют в VBA функцию Round(число,2), принося тем самым кому-то убытки, а кому-то неожиданную прибыль.  
 
Более точно определение банковского округления можно прочесть здесь:  
http://ru.wikipedia.org/wiki/Округление  
 
Реализация (на мой взгляд, не очень оптимальная) разных видов округления, на английском здесь:  
http://support.microsoft.com/default.aspx?scid=kb;en-us;196652  
 
---  
ZVI
 
В дополнение к изложенному ZVI.  
Приведенный способ банковского округления, применяется в геодезии с незапамятных времен, по-видимому, с тех, когда и банков (в современном понимании) не было.  
Да, таким образом уменьшалась систематическая ошибка округления при математической обработке геодезических измерений. А вычисления, еще на моей памяти, проводились с помощью «таблиц семизначных логарифмов» Вега и конторских счетов, альтернативой были «шестизначные таблицы тригонометрических функций» Петерса и железный «Феликс».  
С уважением, Александр.
 
{quote}{login=Sh_Alex}{date=04.06.2008 03:15}{thema=VBA Round()}{post}В дополнение к изложенному ZVI.  
Приведенный способ банковского округления, применяется в геодезии с незапамятных времен, по-видимому, с тех, когда и банков (в современном понимании) не было.  
Да, таким образом уменьшалась систематическая ошибка округления при математической обработке геодезических измерений. А вычисления, еще на моей памяти, проводились с помощью «таблиц семизначных логарифмов» Вега и конторских счетов, альтернативой были «шестизначные таблицы тригонометрических функций» Петерса и железный «Феликс».  
С уважением, Александр.{/post}{/quote}  
 
Эх, а как здорово было считать на счётах нормы естественной убыли товаров! А "Феликс"...  
Всё ушло, всё умчалося в невозвратную даль...  
(Сейчас дедушка Мазай будет ругаться.)
 
--  
Пока дедушка Мазай не пришел с железным "Феликсом" наперевес, разбавим тему VBA-кодом.  
 
Вообще-то я хотел спровоцировать вопрос:  “а как округлять в VBA аналогично Excel?”  
Имея в виду некую  функцию  MyRound(X, N)    
где X – округляемое число,    
а N – количество разрядов округления, как в Excel (положительное, отрицательное или ноль).  
 
Сразу напрашивается: WorksheetFunction.Round(X, N), но это медленная функция, так как относится к классу Application.  
 
Изящная функция попалась когда-то мне в Интернете:  
 
Function MathRound(X As Double, Optional N As Integer = 0) As Double  
MathRound = CDbl(FormatNumber(X, N))  
End Function  
 
Она примерно в 2.4 раза быстрее WorksheetFunction.Round(X, N)  
 
Моя реализация (2007г.) не столь изящно выглядит, но почти в 10 раз быстрее. чем WorksheetFunction.Round(X, N):  
 
Public Function ZVI_Round(X As Double, Optional N As Integer = 0) As Double  
Dim b#  
b = Fix(N)  
If N < 0 Then  
b = 10 ^ -b  
ZVI_Round = Round(X / b + Sgn(X) * 2.222E-16, 0) * b  
Else  
ZVI_Round = Round(X + Sgn(X) * 2.222E-16, b)  
End If  
If Abs(ZVI_Round) = 0 Then ZVI_Round = 0  
End Function    
 
Прилагаю таблицу сравнительного тестирования скорости выполнения 3-х вариантов.  
 
---  
ZVI
 
---  
Прошу исправить, должно быть:  
 
Function ZVI_Round(x, Optional N = 0) As Double  
Dim b#  
b = Fix(N)  
If N < 0 Then  
b = 10 ^ -b  
ZVI_Round = Round(x / b + x * 1E-16, 0) * b  
Else  
ZVI_Round = Round(x + x * 1E-16, b)  
End If  
If Abs(ZVI_Round) = 0 Then ZVI_Round = 0  
End Function  
 
Откорректированый вариант таблицы прилагается  
 
---  
ZVI
 
Последний вариант ZVI_Round() неправильно отрабатывает округление числа 0,5.  
Предыдущая версия работает корректно!
 
Все верно, вроде исправлял. По крайней мере, у меня в архиве корректный вариант :-) Вот правильный вариант арифметического округления, заодно привожу еще одну функцию для округления с заданной точностью:  
 
' ZVI:2009-06-02 VBA arithmetic rounding function  
' Arguments are the same as for WorksheetFunction.Round(V,DecPlaces)  
' Функция, аналогичная =ОКРУГЛ(число;число_разрядов)  
Function ZVI_Round(V As Double, Optional DecPlaces As Integer = 0) As Double  
 If DecPlaces < 0 Then  
   ZVI_Round = Round(V / 10 ^ -DecPlaces + V * 2E-16, 0) * 10 ^ -DecPlaces  
 Else  
   ZVI_Round = Round(V + V * 2E-16, DecPlaces)  
 End If  
 If Abs(ZVI_Round) = 0 Then ZVI_Round = 0  ' Exclude -0 return value  
End Function  
 
' ZVI:2009-06-07 VBA rounding to the desired multiple  
' Like Excel function =MROUND(Value, Multiple) from Analysis ToolPack Add-In  
' Функция, аналогичная =ОКРУГЛТ(число;точность)  
Function ZVI_MRound(V As Double, Optional Multiple As Double = 1) As Double  
 If Multiple = 0 Then Exit Function  
 ZVI_MRound = Round((V + V * 2E-16) / Abs(Multiple), 0) * Abs(Multiple)  
 If Abs(ZVI_MRound) = 0 Then ZVI_MRound = 0  
End Function
 
Function My_Round(ByVal X As Double, Optional ByVal N As Integer = 0) As Double  
   Dim B As Double  
   If N = 0 Then  
       MyRound = Sgn(X) * Int(Abs(X) + 0.5)  
   Else  
       B = 10 ^ -N  
       MyRound = Sgn(X) * B * Int(Abs(X) / B + 0.5)  
   End If  
End Function
 
фото средств измерения упомянутых, и не упомянутых, выше.  
Слева направо: [Железый] Феликс (серийный номер - Г89573), логарифмическая линейка, счёты (mini).
Всё поддерживается в исправном состоянии на случай энергетического каллапса.
 
{quote}{login=}{date=18.02.2011 01:46}{thema=}{post}Function My_Round(ByVal X As Double, Optional ByVal N As Integer = 0) As Double  
   Dim B As Double  
   If N = 0 Then  
       My_Round = Sgn(X) * Int(Abs(X) + 0.5)  
   Else  
       B = 10 ^ -N  
       My_Round = Sgn(X) * B * Int(Abs(X) / B + 0.5)  
   End If  
End Function{/post}{/quote}  
Слишком просто было бы :-)  
Подправил в Вашем коде My_Round вместо MyRound, чтобы все время не получался ноль. А теперь сравните оуругление до 3-знака =ZVI_Round(X;3) и =My_Round(X;3)  
 
...X...ZVI_Round...My_Round  
0,0785 .. 0,079 .. 0,078  
0,5115 .. 0,512 .. 0,511  
0,5035 .. 0,504 .. 0,503  
0,0195 .. 0,020 .. 0,019  
0,0135 .. 0,014 .. 0,013  
0,0115 .. 0,012 .. 0,011  
0,8115 .. 0,812 .. 0,811
 
Да, скорее My_Round - это только алгоритм :(  
Вопрос из треьего ряда аудитории:  
Почему MS не привела правила округления к общему знаменателю,  
на рабочем листе ЦЕЛОЕ() и ОКРУГЛ() - работают по ПРАВИЛЬНО,  
а VBA.Int и VBA.Round - извращенцы ?  
Ответ optional.
 
To k61  
... помню приходил в мамину контору и мне разрешали покрутить Феликс ! ...
 
{quote}{login=}{date=18.02.2011 12:32}{thema=Округление}{post}...  
Почему MS не привела правила округления к общему знаменателю,  
на рабочем листе ЦЕЛОЕ() и ОКРУГЛ() - работают по ПРАВИЛЬНО,  
а VBA.Int и VBA.Round - извращенцы ?{/post}{/quote}  
Сначала был Visual Basic (VB), а затем уже VBA.  
В VB изначально функция Round() выполняла банковское округление, VBA просто наследовал эту функцию, что с точки зрения VB логично. Но возникло противоречие между округлением в VBA и Excel, видимо, посчитали, что так как это разные объектные модели с разными библиотеками, то так логичнее.    
Что касается Int(), то к ней нет претензий. Проблемы возникают из-за способа представления Double чисел: http://support.microsoft.com/kb/78113/ru
 
ZVI, спасибо за пояснения и Вашу UDF.
 
У меня проблема. Нужно округлить число в середине формулы. Например:  
((2,8-2,1)/0,8)*25  
мне нужно значение ((2,8-2,1)/0,8) округлить до целого числа. Можно сделать это в одной формуле?
 
=ОКРУГЛ((2,8-2,1)/0,8;0)*25  
 
чуть короче  
 
=ОКРУГЛ((2,8-2,1)/0,8;)*25
 
А если округлить нужно до 0,5
 
=ОКРУГЛТ(_число_;0,5)
 
{quote}{login=ZVI}{date=17.02.2011 10:43}{thema=}{post}Все верно, вроде исправлял. По крайней мере, у меня в архиве корректный вариант :-) Вот правильный вариант арифметического округления, заодно привожу еще одну функцию для округления с заданной точностью:  
 
' ZVI:2009-06-02 VBA arithmetic rounding function  
' Arguments are the same as for WorksheetFunction.Round(V,DecPlaces)  
' Функция, аналогичная =ОКРУГЛ(число;число_разрядов)  
Function ZVI_Round(V As Double, Optional DecPlaces As Integer = 0) As Double  
 If DecPlaces < 0 Then  
   ZVI_Round = Round(V / 10 ^ -DecPlaces + V * 2E-16, 0) * 10 ^ -DecPlaces  
 Else  
   ZVI_Round = Round(V + V * 2E-16, DecPlaces)  
 End If  
 If Abs(ZVI_Round) = 0 Then ZVI_Round = 0  ' Exclude -0 return value  
End Function  
 
' ZVI:2009-06-07 VBA rounding to the desired multiple  
' Like Excel function =MROUND(Value, Multiple) from Analysis ToolPack Add-In  
' Функция, аналогичная =ОКРУГЛТ(число;точность)  
Function ZVI_MRound(V As Double, Optional Multiple As Double = 1) As Double  
 If Multiple = 0 Then Exit Function  
 ZVI_MRound = Round((V + V * 2E-16) / Abs(Multiple), 0) * Abs(Multiple)  
 If Abs(ZVI_MRound) = 0 Then ZVI_MRound = 0  
End Function{/post}{/quote}  
Уважаемый ZVI, подскажите пожалуйста, а как реализовать функцию аналогичную ОКРУГЛВВЕРХ с помощью VBA
 
как вариант:  
 
Function MyRoundUp(V As Double, Optional DecPlaces As Integer = 0) As Double  
   If Round(V, DecPlaces) = V Then  
       MyRoundUp = V  
   Else  
       MyRoundUp = -Int(-V * 10 ^ DecPlaces) / 10 ^ DecPlaces  
   End If  
End Function
 
'ZVI:2012-02-09 VBA ROUNDUP function  
Function ZVI_RoundUp(V As Double, Optional DecPlaces As Integer = 0) As Double  
 Dim x#  
 x = Fix(V * 10 ^ DecPlaces)  
 If x <> V * 10 ^ DecPlaces Then x = x + 1  
 ZVI_RoundUp = Round(x / 10 ^ DecPlaces, DecPlaces + 1)  
End Function
 
Для полного диапазона отрицательных DecPlaces, правильнее так, с использованием ZVI_Round, приведенной выше:  
 
'ZVI:2012-02-09 VBA ROUNDUP function  
Function ZVI_RoundUp(V As Double, Optional DecPlaces As Integer = 0) As Double  
 Dim x#  
 x = Fix(V * 10 ^ DecPlaces)  
 If x <> V * 10 ^ DecPlaces Then x = x + 1  
 ZVI_RoundUp = ZVI_Round(x / 10 ^ DecPlaces, DecPlaces)  
End Function
 
{quote}{login=ZVI}{date=09.02.2012 12:54}{thema=}{post}'ZVI:2012-02-09 VBA ROUNDUP function  
Function ZVI_RoundUp(V As Double, Optional DecPlaces As Integer = 0) As Double  
 Dim x#  
 x = Fix(V * 10 ^ DecPlaces)  
 If x <> V * 10 ^ DecPlaces Then x = x + 1  
 ZVI_RoundUp = Round(x / 10 ^ DecPlaces, DecPlaces + 1)  
End Function{/post}{/quote}  
 
=ZVI_RoundUp(2,2;2) = 2,21  
=ZVI_RoundUp(46,02;4) = 46,0201  
=ZVI_RoundUp(17,1;5) = 17,10001  
=ZVI_RoundUp(128,717;3) = 128,718  
и т.п.
 
Оказывается VBA Round() в отличии от =ОКРУГЛ() не работает с отрицательным числом разрядов, поэтому MyRoundUp нуждается в доработке:  
Function MyRoundUp(V As Double, Optional DecPlaces As Integer = 0) As Double  
If DecPlaces >= 0 Then  
   If Round(V, DecPlaces) = V Then MyRoundUp = V: Exit Function  
Else  
   If Int(V * 10 ^ DecPlaces + 0.5) = V * 10 ^ DecPlaces Then MyRoundUp = V: Exit Function  
End If  
MyRoundUp = -Int(-V * 10 ^ DecPlaces) / 10 ^ DecPlaces  
End Function
 
Да, погорячился я немного :-)    
А в варианте Михаила (MCH) проблемы с отрицательными числами, например с:  
-0,0785  
-0,5115  
-0,5035  
-0,0005  
-0,0025  
-0,0194  
-0,0195  
-0,0135  
-0,0115  
-0,8115  
-130,223  
и т.п.  
 
Надежнее всего так:  
 
Function RoundUp(v As Double, Optional DecPlaces As Integer = 0) As Double  
 RoundUp = WorksheetFunction.RoundUp(v, DecPlaces)  
End Function
Страницы: 1 2 След.
Читают тему
Наверх