#excel #vba
#excel #vba
Вопрос:
У меня есть следующая пользовательская функция, которая округляет число до заданной пользователем точности.
Оно основано на общей формуле:
ROUND(Value/ Accuracy,0)*Accuracy
Бывают случаи, когда число / точность в точности кратны 0,5, и Excel не выполняет общее правило округления (нечетное число — округление в большую сторону, четное число — округление в меньшую), поэтому я создал пользовательскую функцию.
Function CheckTemp(val As Range, NumAccuracy As Range) As Double
Dim Temp As Double
Temp= Abs(val) / NumAccuracy
CheckTemp = (Temp / 0.5) - WorksheetFunction.RoundDown(Temp / 0.5 , 0)
End Function
Если CheckTemp = 0, то ‘val’ подпадает под этот случай, когда в зависимости от числа я хочу конкретно округлить в меньшую или большую сторону. Если оно равно false, то используется общая команда Round().
У меня действительно странный случай, когда точность = 0.1 и любой ‘val’, который соответствует требованию:
#.X500000000…,
где: ‘X’ — нечетное число или ноль (т.Е. 0,1,3,5,7,9).
В зависимости от целого числа функция не работает.
Пример:
val = - 5 361 202.55
NumAccuracy = 0.1
Temp = 53 612 025.5
Temp / 0.5 = 107 224 051.
WorksheetFunction.RoundDown(Temp / 0.5,0) = 107 224 051.
CheckTemp = -1.49012E-08
Если я разделю эту проверку на две отдельные функции, одну для вывода (Temp / 0.5) и WF.Округление (Temp / 0.5) на листе Excel, а затем вычитание двух на листе, я получаю РОВНО 0.
Однако при кодировании на VBA возникает ошибка, приводящая к ненулевому ответу (еще более тревожным является ОТРИЦАТЕЛЬНОЕ значение, что должно быть невозможно, когда Temp всегда положительный, а округление (‘x’, ‘y’) всегда приводит к меньшему числу, чем ‘x’).
‘val’ может быть очень большим числом со многими десятичными знаками, поэтому я пытаюсь сохранить параметр ‘Double’, если это возможно.
Я попробовал тип переменной ‘Single’, и, похоже, ошибка устраняется с помощью CheckTemp(), но я беспокоюсь, что конечный пользователь может использовать число, превышающее предел переменной ‘Single’.
Комментарии:
1. Скорее всего, ошибка с плавающей запятой.
Ответ №1:
Вы не ошибаетесь, но собственное округление в VBA сильно ограничено.
Итак, используйте правильную функцию округления, такую как RoundMid, как в моем проекте VBA.Круглый. Он использует десятичную дробь, если это возможно, чтобы избежать подобных ошибок.
Пример:
Value = 5361202.55
NumAccuracy = 0.1
RoundedValue = RoundMid(Value / NumAccuracy, 0) * Numaccuracy
RoundedValue -> 5361202.6