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

Вход

Регистрация

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

 

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

Старая форма входа
  • Страница 1 из 1
  • 1
Модератор форума: китин, _Boroda_  
Мир MS Excel » Вопросы и решения » Вопросы по VBA » Почему возникает погрешность при работе с Double и Single? (Макросы/Sub)
Почему возникает погрешность при работе с Double и Single?
Roman777 Дата: Суббота, 16.07.2016, 14:34 | Сообщение № 1
Группа: Проверенные
Ранг: Ветеран
Сообщений: 980
Репутация: 127 ±
Замечаний: 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
Группа: Авторы
Ранг: Ветеран
Сообщений: 903
Репутация: 290 ±
Замечаний: 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
Группа: Проверенные
Ранг: Старожил
Сообщений: 1334
Репутация: 533 ±
Замечаний: 0% ±

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

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

XL 2016
[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
Группа: Проверенные
Ранг: Ветеран
Сообщений: 980
Репутация: 127 ±
Замечаний: 0% ±

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


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

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

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

[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
Группа: Проверенные
Ранг: Ветеран
Сообщений: 980
Репутация: 127 ±
Замечаний: 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
Группа: Проверенные
Ранг: Ветеран
Сообщений: 980
Репутация: 127 ±
Замечаний: 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-2024 · Дизайн: MichaelCH · Хостинг от uCoz · При использовании материалов сайта, ссылка на www.excelworld.ru обязательна!