• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

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

    Запись на курс до 25 апреля. Получить промодоступ ...

Проблема с Double

  • Автор темы divankin
  • Дата начала
D

divankin

Как вы думаете, что будет если выполнить данный код?
Dim rest As Double
rest = 42430.11
rest = rest - 10607.53
rest = rest - 10607.53
rest = rest - 10607.53
rest = rest - 10607.52
Print rest

У меня данный код выводит в консоль не ноль, а 1,81898940354586Е-12
Можно ли где-то подкрутить какие-нибудь настройки клиента или сервера, чтобы избежать таких остатков, а не менять код , везде где используются сравнения вычисляемых значений типа Double?

Клиенты: 6.5.5, 7.0.2 Win32
Сервера: 7.0.3FP1 Linux, 8.0.2FP1 Win32
 

NickProstoNick

Статус как статус :)
Lotus Team
22.08.2008
1 851
27
BIT
0
Ничего гадкого. Просто тебе возвращается приближенное к 0 значение.
Просто надо использовать округление Round.
Я решал такую проблему умножением и делением 1000 и отсечением возможных знаков после запятой. Мне нужна была точность до 3-го знака
Код:
Dim rest As Double
rest = 42430.11 * 100
rest = rest - 10607.53 * 100
rest = rest - 10607.53 * 100
rest = rest - 10607.53 * 100
rest = rest - 10607.52 * 100
Print rest / 100
 
O

Omh

Тоже не ноль.
Интересная ситуация, я когда-то встречался с этим.
Не помню как тогда решил, но наверно смотрел в сторону
Код:
round
.
 

ToxaRat

Чёрный маг
Green Team
06.11.2007
3 332
42
BIT
0
10607.53
внести в переменную типа double
так как в явнов виде оно конвертится почти в long
ко всему прочему тут нужно использовать тип Currency - валюта, там меньше "инженерных приколов"
 
D

divankin

Гадкость в том, что об этой особенности нужно помнить при всех операциях с типом Double. Я как-то не ожидал, что такие проблемы могут возникнуть при сложении и вычитании.
В боевой программе последнего вычитания не было, а вместо него было сравнение. И программа выдавала, что 10607.52 > 10607.52
 
T

turumbay

Гадкость в том, что об этой особенности нужно помнить при всех операциях с типом Double. Я как-то не ожидал, что такие проблемы могут возникнуть при сложении и вычитании.
В боевой программе последнего вычитания не было, а вместо него было сравнение. И программа выдавала, что 10607.52 > 10607.52
это азы программирования. при работе с числами с плавающей точкой:
1. нельзя сравнивать число их с нулем
2. нельзя проверять два таких числа на равенство.( тот же п. 1 )
обычно, вводится константа - т.н. "машинный ноль" , и проверяется abs( floatNumber ) < epsilon.
для большинства реальных задач 1e-6 - достаточная точность.
Ограничение это системное и никак с лотусом не связано.
Java:
double a = 1.1 - 1;
double b = 0.1;
System.out.println( a-b );
Результат: 8.326672684688674E-17
Для уяснения, что данная проблема не зависит от вида операции:
двоичное разложение десятичной дроби 0.1 - бесконечная дробь 0.0(0011), поэтому 0.1 невозможно сохранить в double без потери точности.
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 940
609
BIT
210
и есть тип curency
и эта проблема не специфична домине (как указал коллега)
 
A

Akupaka

это азы программирования
ой! ну хоть кто-то умный вещь сказал! а то я думал, что так и будем думать, что лотус - корень всех на свете проблем...

Гадкость в том, что об этой особенности нужно помнить при всех операциях с типом Double
ну зачем обо всех? обычно нужна точность какого-то результата, а для этого достаточно одной таблетки, т.е. одной операции приведения конечного результата к нужному виду (отображения)
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!