Почему целое число не совпадает при округлении в пользовательской функции?

#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