powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Поломалось округление Double (о черт!)
12 сообщений из 12, страница 1 из 1
Поломалось округление Double (о черт!)
    #36344645
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
MsgBox Round( 4436 . 7705  -  4436 . 7705  / ( 1  +  0 . 18 ) *  0 . 18 ,  2 )
запуск из под IDE дает результат 3759.98
запуск скомпилированного exe-шника дает 3759.97

Меня сейчас не интересует, какой именно должен быть результат (тему округлений подробно разбирали в другой ветке) и что в этой формуле плохо (с темой неточности представления плавающей точки знаком).

Меня интересует, чтобы результат был одинаков. Функция проработала 8 лет, давая одинаковый результат, теперь дает разный. Точного момента поломки отследить не могу, из подозрительных действий на машине ставился только офис ХР (потом снесен). Может он и заменил какую-то библиотеку, я бы понял, если бы на разных компах вдруг оказались разные результаты. Но почему на одной и той же машине? Ведь библиотеки, по идее, должны быть одними и теми же!

Есть у кого какие идеи?
...
Рейтинг: 0 / 0
Поломалось округление Double (о черт!)
    #36344739
Фотография Андрей159
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Поломалось округление Double (о черт!)
    #36344744
Фотография Андрей159
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня XP SP2 тоже выдает ххх.97 компилированый проэкт
...
Рейтинг: 0 / 0
Поломалось округление Double (о черт!)
    #36344768
ZVI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Инфо на всякий случай: в VB и VBA функция Round(1.5,0) = 2 и Round(2.5,0) = 2
То есть, Round() – это банковское округление, а не арифметическое.
Соответственно: Round(1.235,2) = 1.24 и Round(1.245,2) = 1.24

Если нужно оставить такое банковское округление, и получить однозначность в IDE и скомпилированного варианта, то округлите, например, сначала до 3-х знаков, а затем до 2-х: Round(Round(YourDoubleValue,3),2).
Вместо 3 можно использовать 4…12.

Если же требуется арифметическое округление, то можно, например, так:
MsgBox --FormatNumber(4436.7705 - 4436.7705 / (1# + 0.18) * 0.18, 2)
или
MsgBox --Format(4436.7705 - 4436.7705 / (1# + 0.18) * 0.18, "#0.00")

Впрочем, с подобным округлением были разные варианты реализации в разных версиях OLEAUT32.dll – то банковское, то арифметическое, поэтому для арифметического округления я использую свою пользовательскую функцию, которая в раз 14 быстрее, чем приведенные выше:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
' ZVI: VBA arithmetic rounding function
' Arguments are the same as for Excel 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
...
Рейтинг: 0 / 0
Поломалось округление Double (о черт!)
    #36344770
ZVI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В примерах вместо двойного минуса лучше применять CDbl()
...
Рейтинг: 0 / 0
Поломалось округление Double (о черт!)
    #36344787
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ZVI,

Спасибо, но речь не об этом.
Сейчас эту функцию можно было бы доработать как угодно, но в том-то и дело, что она теперь выдает результаты не те, что раньше, то есть некоторые РАНЕЕ рассчитанные документы теперь расчитываются по-другому, и кое-где не сходятся копейки.

Уточню - скомпилированный экзешник работает как и раньше, а вот в IDE стали выдаваться несколько другие результаты.

Вы полагаете, это может быть связано с OLEAUT32.dll? Но я нашел эту библиотеку только в system32 и в dllcache - файлы идентичны.

P.S. Переустановка студии не помогла.
...
Рейтинг: 0 / 0
Поломалось округление Double (о черт!)
    #36344803
ZVI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.Pro,
Варианты решения Вашей проблемы я привел - проверьте, начиная с Round(Round(YourDoubleValue,3),2). У меня все эти варианты выдают одно и то же значение и в IDE и после компилирования.
...
Рейтинг: 0 / 0
Поломалось округление Double (о черт!)
    #36344816
ZVI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ZVIShocker.Pro,
Варианты решения Вашей проблемы я привел - проверьте, начиная с Round(Round(YourDoubleValue,3),2). У меня все эти варианты выдают одно и то же значение и в IDE и после компилирования.
Приложил код и EXE - проверьте, все ли так, как ожидалось.
...
Рейтинг: 0 / 0
Поломалось округление Double (о черт!)
    #36344820
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ZVIShocker.Pro,
Варианты решения Вашей проблемы я привел - проверьте, начиная с Round(Round(YourDoubleValue,3),2). У меня все эти варианты выдают одно и то же значение и в IDE и после компилирования.

Да, они выдают .98 в обоих случаях. Но. Мне нужно, чтобы было .97 (чтобы сохранить совместимость со старыми документами).

Я еще не разбирался досконально (это потребует больших усилий на автоматизацию проверки на сотнях примеров), но мне кажется, что дело не столько в банковском/арифметическом округлении пятерки, сколько в нюансах сложения двух чисел с плавающей точкой в каком-нибудь последнем знаке. Что отчасти подтверждается тем, что если в моем примере заменить (1+0.18) на (1.18), то результат получается уже другой.

Поэтому хотелось бы восстановить работоспособность системы, а потом неспеша спуститься с горы заняться созданием одноззначности формулы (раз уж выявилось такое узкое место).
...
Рейтинг: 0 / 0
Поломалось округление Double (о черт!)
    #36344842
ZVI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Про банковское округление я упомянил на всякий случай. Это не причина Вашей проблемы.
Причина описана здесь: http://support.microsoft.com/kb/78113/ru] Результаты арифметических операций с плавающей точкой в Excel могут быть неточными

Более точный вариант округления как раз выдает EXE вариант, а Вам, получается, нужен менее точный, который подставляет IDE.

Убедиться в том, что шалит именно C:\WINDOWS\system32\oleaut32.dll поможет такой код:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
Private Declare Sub VarRound Lib "C:\WINDOWS\system32\oleaut32.dll" (ByRef pvarIn As Variant, ByVal cDecimals As Long, ByRef pvarResult As Variant)

Function ArithRound(V, Optional DecPlaces =  0 )
    VarRound V, DecPlaces, ArithRound
End Function

Sub Main()
  MsgBox ArithRound( 4436 . 7705  -  4436 . 7705  / ( 1  +  0 . 18 ) *  0 . 18 ,  2 )
End Sub

IDE выдаст 3759.98, а EXE 3759.97
Полагаю, что у Вас всегда так и было, просто не нарывались на пораженные точки округления.
...
Рейтинг: 0 / 0
Поломалось округление Double (о черт!)
    #36344848
ZVI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Думаю, теперь понятно, что проблема - в округлении промежуточных результатов вычислений.
Можно воспроизвести в IDE алгоритм вычислений и округлений EXE.
Разбейте выражение на 2 части в соответствии с порядком вычислений:
Код: plaintext
1.
2.
3.
4.
5.
6.
Sub Main()
  Dim v As Double ' или As Variant
  v =  4436 . 7705  / ( 1  +  0 . 18 ) *  0 . 18 
  v =  4436 . 7705  - v
  MsgBox Round(v,  2 )
End Sub
Так как после каждого действия VB производит округление до 15 значащих чисел, то результат и в IDE и в EXE будет при этом одинаков: 3759.97
...
Рейтинг: 0 / 0
Поломалось округление Double (о черт!)
    #36345137
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ZVIПолагаю, что у Вас всегда так и было, просто не нарывались на пораженные точки округления.

Не было, даю зуб! за один день всплыло сразу три несовпадающих документа, уж на протяжении нескольких лет я бы это отловил!

С остальным поэкспериментирую, спасибо.
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Поломалось округление Double (о черт!)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]