Перейти к содержимому

Арифметика за 3 класс


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 15

#1 Гость_Guest_vboris_*_*

Гость_Guest_vboris_*_*
  • Guests

Отправлено 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_*

Гость_Guest_*
  • Guests

Отправлено 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 imetz

imetz

    Новый участник

  • Members
  • Pip
  • 11 сообщений
  • ФИО:Мец Илья Вадимович

Отправлено 10 ноября 2005 - 07:35

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

1 / 3 = 0.33333333333333

а потом назад

0.33333333333333 * 3= 0.99999999999999

ну и ?
равны ли будут 1 и 0.99999999999999 ?
  • 0

#4 Лена

Лена

    Активный участник

  • Members
  • PipPip
  • 100 сообщений
  • ФИО:Елена

Отправлено 10 ноября 2005 - 08:19

Чтобы этого избежать, можно сделать вот так, если важно 2 знака после запятой: умножить на 100, округлить до целого числа, а потом разделить на 100.
Если 3 знака - то то же самое с 1000 и так далее.
  • 0

#5 Лена

Лена

    Активный участник

  • Members
  • PipPip
  • 100 сообщений
  • ФИО:Елена

Отправлено 10 ноября 2005 - 08:37

И нечего над человеком смеяться, он может всю жизнь на чем-нибудь типа С++ писал, где четкое определение типов и вещественные числа можно сравнивать и вычитать беспроблемно.
  • 0

#6 Гость_Guest_*

Гость_Guest_*
  • Guests

Отправлено 10 ноября 2005 - 08:45

Когда нибудь слышал о представление чисел в копмьютере?

не надо маленьких дурить!

2,3-0,1=2,2
но никак не 2,19999999999999999999997

почему тогда в ТС 2,4-0,1=2,3
а не 2,29999999999999999997 ????

Косяк он и в Африке косяк!!!!
Это надо признавать а не выдумывать ерундовые оправдания о несоответствии типов.
Как победить этот трабл в расчетах - дело уже 48-ое

#7 vBoris

vBoris

    Новый участник

  • Members
  • Pip
  • 7 сообщений
  • ФИО:Boris Vorobiev

Отправлено 10 ноября 2005 - 08:53

2 imetz
что там насчет битиков и байтиков?
не смешите мои тапки, юноша! :fool:

попробуй на калькуляторе набрать 2,3-0,1=??
что видишь? Вот то то!

Да за такие "расчеты" и "обоснования их правильности" любой бухгалтер тебя расстреляет и будет прав. :acute:

+++++++++++++++++++++++++++

вот код смешной
кому не лень- запустите у себя

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

Буду признателен за пояснения от знающих людей
  • 0

#8 Dmitry N

Dmitry N

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 742 сообщений
  • ФИО:Николаев Дмитрий
  • Город:Где-то в России

Отправлено 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

  • 0
С уважением,
Дмитрий

#9 vBoris

vBoris

    Новый участник

  • Members
  • Pip
  • 7 сообщений
  • ФИО:Boris Vorobiev

Отправлено 10 ноября 2005 - 10:00

2 Dmitry N
Благодарю за пояснения.
НО
в данном фрагменте происходит сравнение "в лоб" и оно отрабатывается корректно

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
  • 0

#10 greyver

greyver

    Опытный участник

  • Members
  • PipPipPipPip
  • 358 сообщений
  • ФИО:Вербенко Сергей Анатольевич
  • Город:Москва, Зеленоград


Отправлено 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

  • 0

#11 vBoris

vBoris

    Новый участник

  • Members
  • Pip
  • 7 сообщений
  • ФИО:Boris Vorobiev

Отправлено 10 ноября 2005 - 10:28

Хм. Сравнения с "заданной точностью" получается как в анекдоте
"-Гоги, сколько будет 2+2"
"- 7...8... "
"- правильно, Гоги, не больше 10"


Мда, после 8-ми летней практики в "околокомпьютерной специальности" впервые столкнулся с VBScript и его мягко говоря "своеобразным" функционированием. :fool:
Я ж не спрашивал "как обойти подобный exeption?" (сам могу предложить еще несколько способов), я спрашивал "это у меня руки кривые или у VBScript ?"

Спасибо всем участникам
Ушел (шаркая ржушими тапками) :acute:
  • 0

#12 greyver

greyver

    Опытный участник

  • Members
  • PipPipPipPip
  • 358 сообщений
  • ФИО:Вербенко Сергей Анатольевич
  • Город:Москва, Зеленоград


Отправлено 10 ноября 2005 - 10:33

я спрашивал "это у меня руки кривые или у VBScript ?"


спросите гугла...
  • 0

#13 Лена

Лена

    Активный участник

  • Members
  • PipPip
  • 100 сообщений
  • ФИО:Елена

Отправлено 14 ноября 2005 - 10:43

Вот код на с++
[size=1][code=auto:0]
#include <iostream.h>
#include <math.h>

А если вместо <math.h> попробовать <cmath>?
  • 0

#14 Лена

Лена

    Активный участник

  • Members
  • PipPip
  • 100 сообщений
  • ФИО:Елена

Отправлено 14 ноября 2005 - 10:51

вот код смешной
кому не лень- запустите у себя

Sub Main

Мой молодой коллега, который учится недавно, сказал, что это классический пример... якобы когда говорят, что представление чисел с плавающей точкой неточно, первым делом говорят - не ставьте 0.1 в приращение цикла...
  • 0

#15 Лена

Лена

    Активный участник

  • Members
  • PipPip
  • 100 сообщений
  • ФИО:Елена

Отправлено 14 ноября 2005 - 11:32

А если вместо <math.h> попробовать <cmath>?

Просмотр сообщения

Прошу прощения. И с math, и с cmath попробовала, Вы правы.
  • 0

#16 Лена

Лена

    Активный участник

  • Members
  • PipPip
  • 100 сообщений
  • ФИО:Елена

Отправлено 14 ноября 2005 - 12:10

Вот код на с++

Извините, не могу успокоиться :-)
Будет работать, если вместо double использовать float;
или если поставить double с = 222.1f
Темное дело.
  • 0


Количество пользователей, читающих эту тему: 1

0 пользователей, 1 гостей, 0 анонимных