Домашняя страница Undo Do New Save Карта сайта Обратная связь Поиск по форуму
МИР MS EXCEL - Гость.xls

Вход

Регистрация

Напомнить пароль

 

= Мир MS Excel/Почему возникает погрешность при работе с Double и Single? - Мир MS Excel

Регистрация · Логин: · Пароль: · · Забыли пароль?
  • Страница 1 из 1
  • 1
Модератор форума: _Boroda_, Pelena, Manyasha, SLAVICK  
Мир MS Excel » Вопросы и решения » Вопросы по VBA » Почему возникает погрешность при работе с Double и Single? (Макросы/Sub)
Почему возникает погрешность при работе с Double и Single?
Roman777 Дата: Суббота, 16.07.2016, 14:34 | Сообщение № 1
Группа: Проверенные
Ранг: Ветеран
Сообщений: 846
Репутация: 106 ±
Замечаний: 0% ±

Excel 2007, Excel 2013
Всем доброго дня!
Столкнулся с небольшой проблемой, непонятной для меня. Подскажите. пожалуйста, почему, когда я задаю конечное дробное число, возникают погрешности в приведённом ниже примере?
Какие есть способы борьбы с этим (помимо Round())?
[vba]
Код
Sub test1()
Dim a As Double
Dim b As Single
a = 1234.01
b = 1234.01
MsgBox (a - Fix(a))
MsgBox (b - Fix(b))
End Sub
[/vba]


Много чего не знаю!!!!
 
Ответить
СообщениеВсем доброго дня!
Столкнулся с небольшой проблемой, непонятной для меня. Подскажите. пожалуйста, почему, когда я задаю конечное дробное число, возникают погрешности в приведённом ниже примере?
Какие есть способы борьбы с этим (помимо Round())?
[vba]
Код
Sub test1()
Dim a As Double
Dim b As Single
a = 1234.01
b = 1234.01
MsgBox (a - Fix(a))
MsgBox (b - Fix(b))
End Sub
[/vba]

Автор - Roman777
Дата добавления - 16.07.2016 в 14:34
Rioran Дата: Суббота, 16.07.2016, 14:53 | Сообщение № 2
Группа: Авторы
Ранг: Ветеран
Сообщений: 902
Репутация: 287 ±
Замечаний: 0% ±

Excel 2013
Roman777, привет!

Эта проблема встречается в разных языках программирования. Я видел на примере семейства Java. Проблема связана с тем, что сложно закодировать дробное число с плавающей запятой с помощью бинарного кода на машинном уровне.

Предлагаю такой подход, похоже, работает для типа Double:

[vba]
Код
Sub Test()
    Dim a As Double
    Dim b As Single
    Const xCheck& = 1000000
    a = 1234.01
    b = 1234.01
    a = a * xCheck
    b = b * xCheck
    Debug.Print (a - (a \ xCheck) * xCheck) / xCheck ' Вернёт 0.01
    Debug.Print (b - (b \ xCheck) * xCheck) / xCheck ' Вернёт 0.009984
End Sub
[/vba]


Роман, Москва, voronov_rv@mail.ru
Яндекс-Деньги: 41001312674279
 
Ответить
СообщениеRoman777, привет!

Эта проблема встречается в разных языках программирования. Я видел на примере семейства Java. Проблема связана с тем, что сложно закодировать дробное число с плавающей запятой с помощью бинарного кода на машинном уровне.

Предлагаю такой подход, похоже, работает для типа Double:

[vba]
Код
Sub Test()
    Dim a As Double
    Dim b As Single
    Const xCheck& = 1000000
    a = 1234.01
    b = 1234.01
    a = a * xCheck
    b = b * xCheck
    Debug.Print (a - (a \ xCheck) * xCheck) / xCheck ' Вернёт 0.01
    Debug.Print (b - (b \ xCheck) * xCheck) / xCheck ' Вернёт 0.009984
End Sub
[/vba]

Автор - Rioran
Дата добавления - 16.07.2016 в 14:53
Karataev Дата: Суббота, 16.07.2016, 15:17 | Сообщение № 3
Группа: Проверенные
Ранг: Старожил
Сообщений: 1208
Репутация: 456 ±
Замечаний: 0% ±

Excel
Roman777, Excel тоже считает как тип Double, поэтому можно наверное не переживать, если макрос неправильно подсчитает, т.к. Excel тоже неправильно бы подсчитал.


Киви-кошелек: 9166309108
Яндекс-деньги: 410014131888288
 
Ответить
СообщениеRoman777, Excel тоже считает как тип Double, поэтому можно наверное не переживать, если макрос неправильно подсчитает, т.к. Excel тоже неправильно бы подсчитал.

Автор - Karataev
Дата добавления - 16.07.2016 в 15:17
Саня Дата: Суббота, 16.07.2016, 18:41 | Сообщение № 4
Группа: Друзья
Ранг: Ветеран
Сообщений: 1056
Репутация: 546 ±
Замечаний: 0% ±

XL 2010
[vba]
Код
Sub test2()
Dim a, b
a = 1234.01
b = a

a = CDec(a)

MsgBox (a - Fix(a)) & vbNewLine & (b - Fix(b))
End Sub
[/vba]


Сообщение отредактировал Саня - Суббота, 16.07.2016, 18:41
 
Ответить
Сообщение[vba]
Код
Sub test2()
Dim a, b
a = 1234.01
b = a

a = CDec(a)

MsgBox (a - Fix(a)) & vbNewLine & (b - Fix(b))
End Sub
[/vba]

Автор - Саня
Дата добавления - 16.07.2016 в 18:41
Roman777 Дата: Суббота, 16.07.2016, 18:48 | Сообщение № 5
Группа: Проверенные
Ранг: Ветеран
Сообщений: 846
Репутация: 106 ±
Замечаний: 0% ±

Excel 2007, Excel 2013
Rioran, Karataev, Саня, Спасибо большое за ответы). Karataev, Всё-таки тут принципиальна именно правильность...)


Много чего не знаю!!!!
 
Ответить
СообщениеRioran, Karataev, Саня, Спасибо большое за ответы). Karataev, Всё-таки тут принципиальна именно правильность...)

Автор - Roman777
Дата добавления - 16.07.2016 в 18:48
Саня Дата: Суббота, 16.07.2016, 18:56 | Сообщение № 6
Группа: Друзья
Ранг: Ветеран
Сообщений: 1056
Репутация: 546 ±
Замечаний: 0% ±

XL 2010
да, чтобы ответ на вопрос темы был более ощутим:

[vba]
Код
Sub test1()
Dim a As Double
Dim b As Single
a = 1234.046875 ' 1234.01
b = 1234.046875 ' 1234.01
MsgBox (a - Fix(a))
MsgBox (b - Fix(b))
End Sub
[/vba]
 
Ответить
Сообщениеда, чтобы ответ на вопрос темы был более ощутим:

[vba]
Код
Sub test1()
Dim a As Double
Dim b As Single
a = 1234.046875 ' 1234.01
b = 1234.046875 ' 1234.01
MsgBox (a - Fix(a))
MsgBox (b - Fix(b))
End Sub
[/vba]

Автор - Саня
Дата добавления - 16.07.2016 в 18:56
Roman777 Дата: Суббота, 16.07.2016, 19:16 | Сообщение № 7
Группа: Проверенные
Ранг: Ветеран
Сообщений: 846
Репутация: 106 ±
Замечаний: 0% ±

Excel 2007, Excel 2013
Саня, ощутимее, всё же мне стало вот на таком примере (ну это в сравнении с Вашим первоначальным):
[vba]
Код
Sub test1()
Dim a As Double
Dim b As Single
a = 1234.04687 ' 1234.01
b = 1234.04687 ' 1234.01
MsgBox (a - Fix(a)) 'вернет 4,68699999998989E-02
MsgBox (b - Fix(b)) 'вернет 0,046875
End Sub
[/vba]


Много чего не знаю!!!!

Сообщение отредактировал Roman777 - Суббота, 16.07.2016, 19:20
 
Ответить
СообщениеСаня, ощутимее, всё же мне стало вот на таком примере (ну это в сравнении с Вашим первоначальным):
[vba]
Код
Sub test1()
Dim a As Double
Dim b As Single
a = 1234.04687 ' 1234.01
b = 1234.04687 ' 1234.01
MsgBox (a - Fix(a)) 'вернет 4,68699999998989E-02
MsgBox (b - Fix(b)) 'вернет 0,046875
End Sub
[/vba]

Автор - Roman777
Дата добавления - 16.07.2016 в 19:16
SGerman Дата: Воскресенье, 17.07.2016, 13:58 | Сообщение № 8
Группа: Пользователи
Ранг: Участник
Сообщений: 97
Репутация: 4 ±
Замечаний: 20% ±

Excel 2003
Roman777,

Вы не указали сущность, для которой производятся вычисления. Если это деньги (цена, сумма), то лучше использовать денежный формат.
Если это например нормочасы или нормы расхода, расценки и т.д, то нужно перед арифметическим действием умножать оба числа на 10 в степени дробной точности с округлением до целого каждого из "слагаемых", а потом результат делить на эту же спепень с округлением до нужной степени точности. При умножении делитель должен быть как произведение точностей обоих слагаемых.

Если у Вас делаюся агрегатные вычисления (например, сумма по счету-фактуре, сметная стоимость, товарные отчеты и т.д.), то перечисленные действия необходимо выполнять как для каждой строки, так и при каждом построчном сложении. Такая технология даст практически 100% гарантию точного совпадения подсчитанных результатов с теми, которые условный бухгалтер или сметчик получает "на калькуляторе".


Мудрость приходит со старостью. Но иногда старость приходит одна :)
 
Ответить
СообщениеRoman777,

Вы не указали сущность, для которой производятся вычисления. Если это деньги (цена, сумма), то лучше использовать денежный формат.
Если это например нормочасы или нормы расхода, расценки и т.д, то нужно перед арифметическим действием умножать оба числа на 10 в степени дробной точности с округлением до целого каждого из "слагаемых", а потом результат делить на эту же спепень с округлением до нужной степени точности. При умножении делитель должен быть как произведение точностей обоих слагаемых.

Если у Вас делаюся агрегатные вычисления (например, сумма по счету-фактуре, сметная стоимость, товарные отчеты и т.д.), то перечисленные действия необходимо выполнять как для каждой строки, так и при каждом построчном сложении. Такая технология даст практически 100% гарантию точного совпадения подсчитанных результатов с теми, которые условный бухгалтер или сметчик получает "на калькуляторе".

Автор - SGerman
Дата добавления - 17.07.2016 в 13:58
SGerman Дата: Воскресенье, 17.07.2016, 14:06 | Сообщение № 9
Группа: Пользователи
Ранг: Участник
Сообщений: 97
Репутация: 4 ±
Замечаний: 20% ±

Excel 2003
В дополнение:

Когда-то это была проблема - при подсчете "Итого" в счетах-фактурах или накладных на отпуск итоговая сумма не сходилась с той, которую получал бухгалтер на калькуляторе (были и такие бабушки, которые лихо щелкали на счетах) - приходилось вышеописанную методу вставлять в программы, даже написал для этого небольшую библиотеку (база была на Paradox, позже Delphi+Access)
При переходе на SQL-сервер проблема исчезла, т.к. там умные дяденьки предусмотрели нужные форматы данных


Мудрость приходит со старостью. Но иногда старость приходит одна :)
 
Ответить
СообщениеВ дополнение:

Когда-то это была проблема - при подсчете "Итого" в счетах-фактурах или накладных на отпуск итоговая сумма не сходилась с той, которую получал бухгалтер на калькуляторе (были и такие бабушки, которые лихо щелкали на счетах) - приходилось вышеописанную методу вставлять в программы, даже написал для этого небольшую библиотеку (база была на Paradox, позже Delphi+Access)
При переходе на SQL-сервер проблема исчезла, т.к. там умные дяденьки предусмотрели нужные форматы данных

Автор - SGerman
Дата добавления - 17.07.2016 в 14:06
Roman777 Дата: Понедельник, 18.07.2016, 09:31 | Сообщение № 10
Группа: Проверенные
Ранг: Ветеран
Сообщений: 846
Репутация: 106 ±
Замечаний: 0% ±

Excel 2007, Excel 2013
SGerman, Принципиально не важно было для какого-то случая. Тут работа была с цифрами не имеющими физических (или денежных) интерпретаций. Сам тоже думал о втором варианте, предложенном Вами, но мне показалось это извращением, поэтому спросил...) Спасибо за предложения.


Много чего не знаю!!!!
 
Ответить
СообщениеSGerman, Принципиально не важно было для какого-то случая. Тут работа была с цифрами не имеющими физических (или денежных) интерпретаций. Сам тоже думал о втором варианте, предложенном Вами, но мне показалось это извращением, поэтому спросил...) Спасибо за предложения.

Автор - Roman777
Дата добавления - 18.07.2016 в 09:31
SGerman Дата: Понедельник, 18.07.2016, 12:02 | Сообщение № 11
Группа: Пользователи
Ранг: Участник
Сообщений: 97
Репутация: 4 ±
Замечаний: 20% ±

Excel 2003
Roman777,
Переход на SQL-сервер решает эту проблему полностью. Excel, на мой непросвященный взгляд, должен служить лишь "тонким" клиентом для реализации интерфейса с БД. Все вычисления, проверки и т.д. должны выполняться именно на серверу, для этого там есть бизнес-логика и куча нештяков.
Тем более, что сейчас нет никаких проблем с выбором абсолютно бесплатных серверов.

Имея немалый опыт разработки различных СУБД-проектов, давно пришел к убеждению, что для формирования всевозможных отчетов (в т.ч. и не очень-то табличных) ничего лучше Excel еще не придумано.


Мудрость приходит со старостью. Но иногда старость приходит одна :)
 
Ответить
СообщениеRoman777,
Переход на SQL-сервер решает эту проблему полностью. Excel, на мой непросвященный взгляд, должен служить лишь "тонким" клиентом для реализации интерфейса с БД. Все вычисления, проверки и т.д. должны выполняться именно на серверу, для этого там есть бизнес-логика и куча нештяков.
Тем более, что сейчас нет никаких проблем с выбором абсолютно бесплатных серверов.

Имея немалый опыт разработки различных СУБД-проектов, давно пришел к убеждению, что для формирования всевозможных отчетов (в т.ч. и не очень-то табличных) ничего лучше Excel еще не придумано.

Автор - SGerman
Дата добавления - 18.07.2016 в 12:02
Мир MS Excel » Вопросы и решения » Вопросы по VBA » Почему возникает погрешность при работе с Double и Single? (Макросы/Sub)
  • Страница 1 из 1
  • 1
Поиск:

Яндекс цитирования
© 2010-2018 · Дизайн: MichaelCH · Хостинг от uCoz · При использовании материалов сайта, ссылка на www.excelworld.ru обязательна!