Арифметика за 3 класс
#1 Гость_Guest_vboris_*_*
Отправлено 09 ноября 2005 - 22:32
или я такой везучий или я ничего не понимаю.
создаем проект VB
пишем в юнит
Sub Main
a=222.3
c=0.2
b=a-c
Log.Message(b )
d=222.1
log.Message(d )
if(b<>d) then Log.Error("res2 = "&d&"<>"&b )
End Sub
смотрим лог
Message
res2 = 222,1<>222,1
меняем в юните
Sub Main
a=222.1
c=0.2
b=a-c
Log.Message(b )
d=222.0
log.Message(d )
if(b<>d) then Log.Error("res2 = "&d&"<>"&b )
End Sub
смотрим лог
все нормально.
Детльные исследования показали что ТС расчитывает b=a-c=222,1999999999997 НО ТОЛЬКО в случае, если десятичная часть числа =0,3
Прокомментируйте кто-нибудь, а не то я арифметику за 3 класс съем!
#2 Гость_Guest_*
Отправлено 09 ноября 2005 - 22:35
изменения в юните вот такие
Sub Main
a=222.2
c=0.2
b=a-c
Log.Message(b )
d=222.0
log.Message(d )
if(b<>d) then Log.Error("res2 = "&d&"<>"&b )
End Sub
лог показывает "ОК"
#3
Отправлено 10 ноября 2005 - 07:35
Про то, что они представляются на самом деле битиками и байтиками?
Просто напросто, вещественные числа нельзя так сравнивать в программах ...
Это все равно что ты посчитаешь на калькуляторе:
1 / 3 = 0.33333333333333
а потом назад
0.33333333333333 * 3= 0.99999999999999
ну и ?
равны ли будут 1 и 0.99999999999999 ?
#4
Отправлено 10 ноября 2005 - 08:19
Если 3 знака - то то же самое с 1000 и так далее.
#5
Отправлено 10 ноября 2005 - 08:37
#6 Гость_Guest_*
Отправлено 10 ноября 2005 - 08:45
не надо маленьких дурить!Когда нибудь слышал о представление чисел в копмьютере?
2,3-0,1=2,2
но никак не 2,19999999999999999999997
почему тогда в ТС 2,4-0,1=2,3
а не 2,29999999999999999997 ????
Косяк он и в Африке косяк!!!!
Это надо признавать а не выдумывать ерундовые оправдания о несоответствии типов.
Как победить этот трабл в расчетах - дело уже 48-ое
#7
Отправлено 10 ноября 2005 - 08:53
что там насчет битиков и байтиков?
не смешите мои тапки, юноша!
попробуй на калькуляторе набрать 2,3-0,1=??
что видишь? Вот то то!
Да за такие "расчеты" и "обоснования их правильности" любой бухгалтер тебя расстреляет и будет прав.
+++++++++++++++++++++++++++
вот код смешной
кому не лень- запустите у себя
Sub Main
b=0.1
d=2.2
for a=2.1 to 2.9 step 0.1
cс=a-b
log.message(сс)
if (cс=d)then log.error("совпадение")
next
log.message("--------------------------")
b=0.1
d=2.2
a=2.3
cс=a-b
if (cс=d)then
log.error("совпадение")
else
log.error("болт")
end if
End Sub
Буду признателен за пояснения от знающих людей
#8
Отправлено 10 ноября 2005 - 09:49
Ну, начнем с того, что так себя ведет Microsoft VBScript. Проверить это просто - сохранить следующий код в файл с расширением vbs и выполнить его из Explorer'а.
a = 222.3 c = 0.2 b = a-c d = 222.1 if b <> d then MsgBox("res2 = " & d & " <> " & b)
По поводу причины такого поведения я согласен с imetz и Леной, это из-за формы представления чисел с плавающей запятой в компьютере. То, что действительные числа нельзя сравнивать таким образом "в лоб", рассказывают на первом курсе всех околокомпьютерных специальностей.
Лучше их сравнивать так:
a = 222.3 c = 0.2 b = a-c d = 222.1 if Abs(b - d) > 0.0001 then MsgBox "false" else MsgBox "true" end if
Дмитрий
#9
Отправлено 10 ноября 2005 - 10:00
Благодарю за пояснения.
НО
в данном фрагменте происходит сравнение "в лоб" и оно отрабатывается корректно
b=0.1
d=2.2
for a=2.1 to 2.9 step 0.1
cс=a-b
log.message(сс)
if (cс=d)then log.error("совпадение")
next
#10
Отправлено 10 ноября 2005 - 10:06
Нет, Вы не правы. Это проблема, так сказать общего характера, если этим специально не озадачиваться, то числа с плавающей точкой нельзя сравнивть в лоб.И нечего над человеком смеяться, он может всю жизнь на чем-нибудь типа С++ писал, где четкое определение типов и вещественные числа можно сравнивать и вычитать беспроблемно.
Вот код на с++
#include <iostream.h> #include <math.h> void main() { double a,b,c,d; a=222.3; c=0.2; d=222.1; b=a-c; cout << a << " - a\n"; cout << b << " - b\n"; cout << c << " - c\n"; cout << d << " - d\n"; //сравнение "в лоб" if (b==d) { cout << b << " equal " << d << "\n"; }else{ cout << "!!!" << b << " not equal " << d << "\n"; }; //сравнение с заданной точностью if (fabs(b-d)< 1e-10) { cout << b << " equal " << d << "\n"; }else{ cout << "!!!" << b << " not equal " << d << "\n"; }; }
Сообщение отредактировал greyver: 10 ноября 2005 - 10:19
#11
Отправлено 10 ноября 2005 - 10:28
"-Гоги, сколько будет 2+2"
"- 7...8... "
"- правильно, Гоги, не больше 10"
Мда, после 8-ми летней практики в "околокомпьютерной специальности" впервые столкнулся с VBScript и его мягко говоря "своеобразным" функционированием.
Я ж не спрашивал "как обойти подобный exeption?" (сам могу предложить еще несколько способов), я спрашивал "это у меня руки кривые или у VBScript ?"
Спасибо всем участникам
Ушел (шаркая ржушими тапками)
#12
Отправлено 10 ноября 2005 - 10:33
#13
Отправлено 14 ноября 2005 - 10:43
А если вместо <math.h> попробовать <cmath>?Вот код на с++
[size=1][code=auto:0]
#include <iostream.h>
#include <math.h>
#14
Отправлено 14 ноября 2005 - 10:51
Мой молодой коллега, который учится недавно, сказал, что это классический пример... якобы когда говорят, что представление чисел с плавающей точкой неточно, первым делом говорят - не ставьте 0.1 в приращение цикла...вот код смешной
кому не лень- запустите у себя
Sub Main
#16
Отправлено 14 ноября 2005 - 12:10
Извините, не могу успокоиться :-)Вот код на с++
Будет работать, если вместо double использовать float;
или если поставить double с = 222.1f
Темное дело.
Количество пользователей, читающих эту тему: 1
0 пользователей, 1 гостей, 0 анонимных