powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Сравнение чисел double
43 сообщений из 43, показаны все 2 страниц
Сравнение чисел double
    #37453847
Pavel09
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
n1 = 10000.00
n2 = 21832.60-11832.60

? n1-n2

Результат - 0.00

? (n1-n2)*10000000000

Результат - 0.02
Т.е, в первом сравнении результат тоже не 0, а просто округлен до 2-х знаков
Логично было бы в этом случае, чтобы результат выражения

? (n1-n2)==0.00

был .F.

но он .T.

В связи с этим возникает вопрос. Как выполняется сравнение numeric, внутренний формат которых double ?
Это не точное сравнение, а сравнение с учетом некоторой погрешности ?
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37453913
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Фокс хранит нумерик переменные как восьмибайтное двоичное с плавающей запятой.

В хэлпе на фокс заявлена 16-тизначная точность и есть пометка что реально 15,95 знаков, т.е. не все 16-тизначные точно покажутся, у некоторых возможно изменение на 1 младшего разряда.
Это связано с погрешностями преобразования десятичных чисел в восьмибайтное двоичное с плавающей запятой. И касается не только фокса, а всех прог использующих такой тип при расчетах.

Твой пример у меня нормально отрабатывает
Код: plaintext
1.
2.
3.
4.
5.
6.
n1 =  10000 . 00 
n2 =  21832 . 60 - 11832 . 60 

r = n1-n2
? r &&  0 . 0000 
? r ==  0 . 00  && .T.
? r* 10000000000  &&  0 . 0182 

Рекомендую почаще делать округление при расчетах
Код: plaintext
1.
2.
3.
r = round(n1-n2,  2 )
? r &&  0 . 00 
? r ==  0 . 00  && .T.
? r* 10000000000  &&  0 . 00 
или использовать тип CURRENCY для денежных расчетов, правда у него свои подводные камни есть.
Код: plaintext
1.
2.
3.
4.
5.
6.
n1 = $ 10000 . 00 
n2 = $ 21832 . 60 -$ 11832 . 60 

r = n1-n2
? r  &&  0 . 0000 
? r ==  0 . 00   && .T.
? r* 10000000000  &&  0 . 0000 
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37453936
Pavel09
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
По поводу особенностей операций с 8-ми байтными double я в курсе, что результат операции может быть не 0, а какое-то очень малое значение. И по поводу типа Currency тоже.
Вопрос заключается не в этом.
В приведенном примере как раз возникает такой случай, и сравнение двух значений должно давать .F.. Но оно дает .T.
Почему ? Как фокс сравнивает 2 числа double ? С учетом какой-то погрешности, так получается ?
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37453967
Pavel09
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dima T
Код: plaintext
1.
2.
3.
4.
5.
6.
n1 =  10000 . 00 
n2 =  21832 . 60 - 11832 . 60 

r = n1-n2
? r &&  0 . 0000 
? r ==  0 . 00  && .T.
? r* 10000000000  &&  0 . 0182 
[/src]

Я уточню

Исходя из того, что

? r*10000000000 && 0.0182

получается, что r не ноль, и сравнение с нулем должно давать .F.
Если написать этот код на C, то так и получится
Но фокс при сравнении с нулем дает .T.
Значит, у фокса алгоритм сравнения не просто сравнение двух значений, а какой-то другой
Меня интересует, какой
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37454369
SSn888
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Pavel09Dima T
Код: plaintext
1.
2.
3.
4.
5.
6.
n1 =  10000 . 00 
n2 =  21832 . 60 - 11832 . 60 

r = n1-n2
? r &&  0 . 0000 
? r ==  0 . 00  && .T.
? r* 10000000000  &&  0 . 0182 
[/src]

Я уточню

Исходя из того, что

? r*10000000000 && 0.0182

получается, что r не ноль, и сравнение с нулем должно давать .F.
Если написать этот код на C, то так и получится
Но фокс при сравнении с нулем дает .T.
Значит, у фокса алгоритм сравнения не просто сравнение двух значений, а какой-то другой
Меня интересует, какой

а как насчет поставить перед всем этим
SET DECIMALS TO 18
и "конкретизировать четкость сравнения"?
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37454425
Pavel09
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SSn888а как насчет поставить перед всем этим
SET DECIMALS TO 18
и "конкретизировать четкость сравнения"?

Я, собственно, не фокспрошник, и пришел на этот форум из

http://clipper.borda.ru/?1-4-0-00000596-000-0-0-1316771302

где обсуждается такой же вопрос. Меня заинтересовало, как фокс сравнивает double так, что игнорируются ошибки округления.
Что такое set decimals, я конечно знаю. Эта настройка определяет количество десятичных знаков для отображения, но никак не для сравнения. В фоксе, насколько я понимаю, неявно она используется и для алгоритма сравнения.

Но даже в msdn об этом ничего не сказано:

http://msdn.microsoft.com/en-us/library/azeb8csc(VS.80).aspx

Причем, если изменить set decimals после выполнения сравнения, то новая настройка на последющие операции сравнения не повлияет.

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

В любом случае, спасибо за ответы.
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37454547
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот здесь http://forum.foxclub.ru/read.php?29,401694,page=5 почитайте ответ Igor Korolyov Дата: 08.09.09 17:04:09

Igor KorolyovСпособ описания числового литерала в исходном коде влияет как на собственно "значение", так и на эти служебные поля - поэтому и существует разница между написанием ln1 = 2.05 и ln1 = 2.05000000
(...)
Как видно из примера - фокс пытается кое где применить "человеческую" логику и таки провести неявное округление для целей сравнения (и не только сравнения, кстати)

Про структуру хранения в оперативной памяти есть только со времен FoxPro for DOS. Более свежей документации нет. Например, можно посмотреть здесь http://forum.foxclub.ru/read.php?29,378070,page=2
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37455418
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
[quot Pavel09]SSn888....
Свой вопрос я собственно задал для того, чтобы, возможно, в харборе использовать алгоритм сравнения фокса. Перенять, так сказать, передовой опыт....
Явно это нигде не описано, но фокс кроме значения похоже хранит точность: количество десятичных знаков после запятой (возможно количество десятичных разрядов).
И точность результата определяется точностью операндов и операцией. Например при сложении берется максимальная точность, при умножении - произведение точностей и т.д.
Сравнение похоже идет с учетом точности сравниваемых значений.
Код: plaintext
1.
2.
3.
4.
5.
6.
n1 =  12 . 0 
n2 =  13 . 45 

? n1 + n2 &&  25 . 45 
? n1 * n2 &&  161 . 400 
r = round(n1 * n2,  1 )
? r &&  161 . 4 
PS Почаще ROUND() надо использовать и тогда не будет проблем со сравнениями.
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37456587
SSn888
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TИ точность результата определяется точностью операндов и операцией. Например при сложении берется максимальная точность, при умножении - произведение точностей и т.д.
гы...
при делении аналогично
а при вычитании точность соответственно - залезает в минуса :(

максимально возможная точность, если не указана явно - определяется исходя из минимальной чисел в выражении, _отталкиваясь_от_типа_данных_

логическая ошибка была в самом начале на уровне "Как выполняется сравнение numeric, внутренний формат которых double"
и предположения, что присваивание
n1 = 10000.00
n2 = 21832.60-11832.60
дает doble этим переменным

то есть - при отсутствии предварительного декларирования переменных указании фокс сам решает, какой тип ей назначить, когда ей дается значение... по умолчанию - в нашем примере он назначает ей вовсе ну double, а обычное число с плавающей точкой, точность которого - не больше двух десятков
если хотите честно работать именно с double (точность, если не изменяет памать - больше 3 сотен - укажите это сперва перед вашим примером
LOCAL n1 as doub,;
n2 as doub
и "будет Вам щастье"

PS:
вот выдержка из доки:
"When storing floating-point numbers in Numeric fields, numeric precision is limited to approximately 15 digits in Visual FoxPro
...
This limitation is based on the way Pentium-based processors calculate and store floating-point numbers and follows the Institute of Electrical and Electronics Engineers (IEEE) floating-point specification for manipulating floating-point numbers in binary format. This standard makes it possible for floating-point numbers to be stored in reasonable amount of space and for performing calculations more quickly.
...
For values requiring higher precision, see Double Field Type."
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37456588
SSn888
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SSn888,

не совсем закончил

ROUND тут не просто не "надо почаще", а "стоит пореже", чтоб не ввести себя самого нечаянно в заблуждение насчет надежности результата (если она определяется только автоприсвоенным типом данных и нашим ROUND)
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37456659
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SSn888Dima TИ точность результата определяется точностью операндов и операцией. Например при сложении берется максимальная точность, при умножении - произведение точностей и т.д.
гы...
при делении аналогично
а при вычитании точность соответственно - залезает в минуса :(
гыгы вычитание = сложение с отрицательным числом. арифметика 3-4 класс.

SSn888максимально возможная точность, если не указана явно - определяется исходя из минимальной чисел в выражении, _отталкиваясь_от_типа_данных_
В фоксе нет явных числовых типов данных (как в Си например), все числа хранятся в своем double с точностью, за исключением CURRENCY.
В любом случае тип задается в момент присвоения значения, а не в LOCAL\PRIVATE\PUBLIC.


SSn888...
если хотите честно работать именно с double (точность, если не изменяет памать - больше 3 сотен - укажите это сперва перед вашим примером
LOCAL n1 as doub,;
n2 as doub
и "будет Вам щастье"
Так с ним самым фокс и работает. double - 8-байтное двоичное число с плавающей запятой. Точность те самые 15,95 знаков. Возможные значения +/-4.9E-324 to +/-8.9E307
"LOCAL n1 as doub" не делает переменную типа double, все что после "AS" используется при подсказках IntelliSense, а при исполнении игнорируется. Выполни:
Код: plaintext
1.
local x as doub
? vartype(x) 
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37456668
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SSn888SSn888,

не совсем закончил

ROUND тут не просто не "надо почаще", а "стоит пореже", чтоб не ввести себя самого нечаянно в заблуждение насчет надежности результата (если она определяется только автоприсвоенным типом данных и нашим ROUND)
ROUND() надо там где он должен быть по логике задачи. Я это четко усвоил после войны с главбухом когда по одним и тем же расчетным данным итого не сошлось на копейку в разных отчетах, в обоих печаталось одинаково с точностью до копеек, а при расчете "итого" округлялось только в одном.
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37457219
SSn888
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T,

про вычитание я вроде как прикололся... или забыл смайл поставить? :)

"В фоксе нет явных числовых типов данных" - ссылку на msdn дать или сами найдете? :)

"все числа хранятся в своем double с точностью"... ого! значит - я зря привел пример из _официальной_документации_? Вруть все разработчики? %) )

"В любом случае тип задается в момент присвоения значения, а не в LOCAL\PRIVATE\PUBLIC."... Дима... очень не люблю как-то резко говорить людям... но тут... ОКРОПИТЕ ЕГО КТО-НИТЬ СВЯТОЙ ВОДОЙ, ДАБЫ ИЗГНАТЬ СЕГО БЕСА! РТФМ!

local x as doub декларирует, что "в эту переменную будут занесены данные такого типа"... если данные НЕ занесены - какие вопросы?
Работа идет по принципу коробок
Если я говорю "Приготовь для этого самаю большую коробку" - фокс ее подготавливает и ждет что я запихаю
Если же не говорю, а просто предлагаю ему "загнать куда-нить вот это" - он просто берет наименьшую коробку из того, что может подойти, бо "нефиг колхозное добро транжирить"
И еще вот интересно - а для чего, следуя Вашей логике тогда разработчики вообще приделали это "AS " после декларирования переменной, если Вы утверждаете, что "оно ничего и не значит"? Так, чтоб поразвлекаться, наблюдая, как люди это в форуме обсуждают? ;):)

"Выполнит
local x as doub
? vartype(x)".
ну тут вооще... а как насчет доку почитать?!
цицирую хелп для vartype:
"Return value / Data type
N / Numeric, Float, Double, or Integer"
Что Вы хотели доказать своим примером?
Что фокс этой функцией возвращает N для любого из 4-х типов?
вартайп не даст Вам проверить, что у Вас - Float или вообще просто Int
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37457225
SSn888
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TSSn888SSn888,

не совсем закончил

ROUND тут не просто не "надо почаще", а "стоит пореже", чтоб не ввести себя самого нечаянно в заблуждение насчет надежности результата (если она определяется только автоприсвоенным типом данных и нашим ROUND)
ROUND() надо там где он должен быть по логике задачи. Я это четко усвоил после войны с главбухом когда по одним и тем же расчетным данным итого не сошлось на копейку в разных отчетах, в обоих печаталось одинаково с точностью до копеек, а при расчете "итого" округлялось только в одном.

без обид
но усваивать надо в результате обучения, чтения документации и так далее, а не как итог боевой операции.
как я уже говорил - чтоб не ввести нечаянно самого себя в заблуждение.
то, что Вы решили эту проблему роундом - вовсе не говорит, что это был единственный, и главное - наилучший вариант
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37457367
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SSn888"все числа хранятся в своем double с точностью"... ого! значит - я зря привел пример из _официальной_документации_? Вруть все разработчики? %) )
Почему врут? недоговаривают :) Ссылку давай, переведу корректно.

SSn888"Выполнит
local x as doub
? vartype(x)".
ну тут вооще... а как насчет доку почитать?!
цицирую хелп для vartype:
"Return value / Data type
N / Numeric, Float, Double, or Integer"
Что Вы хотели доказать своим примером?
Запустить религия не позволила? vartype(x) вернет тип LOGICAL т.к. всем переменным объявленным в LOCAL присваивается .F., потому что написанное после AS игнорируется при выполнении.

Numeric, Float, Double, or Integer имеют значение когда это в DBF сохраняется, т.к. там под хранение отводится конкретное количество байт и каждый из типов имеет свои ограничения и размеры. Тут разработчик решает какой тип меньше места в файле займет в зависимости от решаемой задачи.

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

Вот почитай про DOUBLE этот тип придуман Интелом и зашит в математический сопроцессор еще со времен 286 процессоров, поэтому все языки его используют одинаково.
При этом есть проблема преобразования дробных чисел из двоичного в десятичный формат - оно редко преобразовывается точно, почти всегда возникает хвост из кучи девяток или нулей с единичкой, поэтому в фоксе это полечили дополнительным ограничением точности (округлением) при выводе. При расчетах этот хвост не мешает, т.к. дает погрешность не влияющую на результат.

PS я к тому что DOUBLE бесполезно указывать т.к. оно и так используется изначально, и точность у него 15,95 десятичных знаков (2^52), никак не около трехсот. Точнее чем с DOUBLE фокс не может расчеты вести. За исключением CURRENCY где при определенном изврате можно получить 18 точных десятичных знаков.
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37457401
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SSn888И еще вот интересно - а для чего, следуя Вашей логике тогда разработчики вообще приделали это "AS " после декларирования переменной, если Вы утверждаете, что "оно ничего и не значит"?
Я ж написал, для выдачи подсказок IntelliSense. Появилось это только в 7 или 8 фоксе.
Можно написать
Код: plaintext
1.
local x as Timer
x.
когда поставишь точку выйдет подсказка со всеми свойствами и методами класса TextBox. Но чтобы ты не написал после точки этот код будет нерабочим, т.к. чтобы переменная Х стала объектом класса Timer надо явно писать
Код: plaintext
X = NewObject('Timer')
и только потом пользовать его свойства и методы.
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37457440
SSn888
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
мдя
разговор вырождается в бодание...
оно мне надо?
ладно, ещ ответ

Dima TSSn888"все числа хранятся в своем double с точностью"... ого! значит - я зря привел пример из _официальной_документации_? Вруть все разработчики? %) )
Почему врут? недоговаривают :) Ссылку давай, переведу корректно.

гм... неужели народ разучился по сайтам поддержки лазать?
http://msdn.microsoft.com/en-us/library/Aa977951.aspx

Specifies the data type on which this variable or array is based.

Dima TЗапустить религия не позволила? vartype(x) вернет тип LOGICAL т.к. всем переменным объявленным в LOCAL присваивается .F., потому что написанное после AS игнорируется при выполнении.
Если человек в качестве аргумента приводит тот факт, что переменная, которой не дали явно значение - будет булевская...
мне нечего сказть... продолжайте в том же духе
"ушла весна, настало лето - спасибо партии за это"

Про тип я читал, переживать не стоит :)

Dima TPS я к тому что DOUBLE бесполезно указывать т.к. оно и так используется изначально, и точность у него 15,95 десятичных знаков (2^52), никак не около трехсот. Точнее чем с DOUBLE фокс не может расчеты вести. За исключением CURRENCY где при определенном изврате можно получить 18 точных десятичных знаков.

Я все-таки хотел бы услышать иной вариант эээ... квалифицированного перевода фразы "Specifies the data type on which this variable or array is based.", где бы объяснялось (1) почему AS фигня и (2) зачем тогда ее разработчики засунули...
Не надо уводить разговор в скользкую канаву - конкретно (цицирую) "потому что написанное после AS игнорируется при выполнении"...
Впрочем - я не удивлюсь если следующий аргумент будет "OF ClassLib тоже игнорируется, попробуй - получищь федю"

еще раз - по умолчанию, если нет явных объяв - фокс выделяет наиболее экономный вариант
число 8.4546 никогда не встанет "само" double, потому что просто Num для него выгодней
можно еще больше утрировать пример, дать значение "8" без точек и потом долго рассуждать, что "DOUBLE бесполезно указывать т.к. оно и так используется изначально"
жуть
"DOUBLE бесполезно указывать т.к. оно и так используется изначально".... "мы позвонили в такси и вызвали машину. - так вы же переезжаете, вы им сказали, что грузовик нужен? - это бесполезно и бессмысленно указывать потому что (1) диспетчера все равно при обработке игнорируют такие слова и (2) все равно система так построена что они по умолчанию при каждом вызове Камаз присылают"
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37457442
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что касается хэлпа то там очень мутно написали How to: Implement Strong Typing for Class, Object, and Variable Code
Вроде как есть строгая типизация и тут же что ее нет:
"... Note: Visual FoxPro is not a strongly typed language and does not require that you declare variables with a specific data types. Visual FoxPro does not enforce strong typing at design time or run time...."
Тут перевод
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37457450
SSn888
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T,

человек, который даже после намеков действительно всеръез полагает, что я не могу перевести столь простую фразу - мне не интересен и пахнет снобизном, а не диалогом...
желаю удачи, я самоустраняюсь от этого
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37457465
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SSn888гм... неужели народ разучился по сайтам поддержки лазать?
http://msdn.microsoft.com/en-us/library/Aa977951.aspx

Specifies the data type on which this variable or array is based.
там же ниже:
Variables and arrays created with LOCAL are initialized to false (.F.)

SSn888Dima TЗапустить религия не позволила? vartype(x) вернет тип LOGICAL т.к. всем переменным объявленным в LOCAL присваивается .F., потому что написанное после AS игнорируется при выполнении.
Если человек в качестве аргумента приводит тот факт, что переменная, которой не дали явно значение - будет булевская... мне нечего сказть... продолжайте в том же духе
Хватит говорить, скопипасти и запусти.

Лично я соглашусь что я не прав, сто раз извинюсь, проставлюсь пивом/водкой/коньяком если меня кто-нибудь научит как в фоксе явно задать тип переменной и чтоб фокс давал ошибку при присвоении переменной значения другого типа.
Достаточно простого примера типа:
Код: plaintext
1.
local x as double
x = 'qwe' && тут сообщение об ошибке.

Не типизированный язык VFP чего бы в хэлпе ни писали.
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37457552
Pavel09
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SSn888Dima TИ точность результата определяется точностью операндов и операцией. Например при сложении берется максимальная точность, при умножении - произведение точностей и т.д.
гы...
при делении аналогично
а при вычитании точность соответственно - залезает в минуса :(

максимально возможная точность, если не указана явно - определяется исходя из минимальной чисел в выражении, _отталкиваясь_от_типа_данных_

логическая ошибка была в самом начале на уровне "Как выполняется сравнение numeric, внутренний формат которых double"
и предположения, что присваивание
n1 = 10000.00
n2 = 21832.60-11832.60
дает doble этим переменным

то есть - при отсутствии предварительного декларирования переменных указании фокс сам решает, какой тип ей назначить, когда ей дается значение... по умолчанию - в нашем примере он назначает ей вовсе ну double, а обычное число с плавающей точкой, точность которого - не больше двух десятков
если хотите честно работать именно с double (точность, если не изменяет памать - больше 3 сотен - укажите это сперва перед вашим примером
LOCAL n1 as doub,;
n2 as doub
и "будет Вам щастье"

PS:
вот выдержка из доки:
"When storing floating-point numbers in Numeric fields, numeric precision is limited to approximately 15 digits in Visual FoxPro
...
This limitation is based on the way Pentium-based processors calculate and store floating-point numbers and follows the Institute of Electrical and Electronics Engineers (IEEE) floating-point specification for manipulating floating-point numbers in binary format. This standard makes it possible for floating-point numbers to be stored in reasonable amount of space and for performing calculations more quickly.
...
For values requiring higher precision, see Double Field Type."

Имеется в виду iee 754 одинарной точности aka float, что ли ? Нет, даже с 8-ми байтным double результат упомянутого выражения будет не ноль, а что-то вроде 2**-39
Если сделать простенький тест:

Local n1 = 10000.00
Local n2, n3, i
Local i1 = 0
Local i2 = 0
for i = 1 to 10000000
n2 = Round(n1+i*0.01, 2)
n3 = Round(n1+n1+i*0.01, 2)
if n1-(n3-n2)*10000000000 = 0.00
i1 ++
else
i2 ++
endif
next
? i1, i2

То видно, что где-то примерно в 13% случаев (для double, не для float) возникает погрешность.
Подобная этой програмка на С, если в ней прямо указать тип double, даст тот же результат.
И никакая заявленная точность в 16 разрядов не работает.
Вот такая она, арифметика чисел с плавающей точкой.
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37457576
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SSn888еще раз - по умолчанию, если нет явных объяв - фокс выделяет наиболее экономный вариант
число 8.4546 никогда не встанет "само" double, потому что просто Num для него выгодней
Экономный для чего? Чего экономим? Повторяю числовые типы для экономии места в DBF, поэтому с точки зрения переменных от такой экономии ни жарко ни холодно. Переменных в фоксе м.б. максимум 65535 поэтому не принципиально займут их значения 1 байт или 8.

Переменным важнее экономия времени, т.е. производительность при расчетах. С этой точки зрения тип DOUBLE оптимален т.к. с ним процессор выполняет математические операции без каких либо предварительных преобразований.
Заводить кучу типов переменных для хранения чисел тоже плохо, т.к. при расчетах необходимо будет делать приведение типов, на что надо время.
К сожалению этот момент никак разработчиками не объясняется, как косвенный аргумент могу привести то что vartype() возвращает "N" для "Numeric, Float, Double, or Integer", т.е. все эти типы физически одинаково сохраняются в переменную при считывании из DBF, иначе зачем разработчикам объединять разные типы? CURENCY они ведь сюда не вставили, потому что он по другому физически хранится в переменной. Это восьмибайтное целое.
SSn888Dima T,

человек, который даже после намеков действительно всеръез полагает, что я не могу перевести столь простую фразу - мне не интересен и пахнет снобизном, а не диалогом...
желаю удачи, я самоустраняюсь от этого
Извини если чем обидел, не знаю как давно ты с фоксом работаешь (был опыт работы с VFP6 и ранее?), но предмет нашего спора это не изначально заложенный функционал, а сбоку прилепленный костыль с подачи маркетологов, прилепленный с целью прикрутить к фоксу подсказки при наборе кода в IDE, которые были в других языках на момент выхода VFP7
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37457611
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Pavel09, ерунда какая-то у тебя в коде, при
n2 = Round(n1+i*0.01, 2)
n3 = Round(n1+n1+i*0.01, 2)

n1-(n3-n2)*10000000000 => (1 - n1) * 10000000000
вобщем далеко не 0 получается
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37457911
Pavel09
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dima TPavel09, ерунда какая-то у тебя в коде,

Да, прошу прощения, переводил с другого языка, скобки забыл поставить, и еще кое-какие огрехи
Вот запусти:

Public n1
n1 = 10000.00
Public n2, n3, i
Public i1, i2
i1 = 0
i2 = 0
for i = 1 to 10000000
n2 = Round(n1+i*0.01, 2)
n3 = Round(n1+n1+i*0.01, 2)
if (n1-(n3-n2))*10000000000 = 0.00
i1 = i1 + 1
else
i2 = i2 + 1
endif
next
? i1, i2
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37458089
XAndy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Pavel09,

все числовые значения в фоксе хранятся в виде сишных структур, где помимо типа и значения есть и ширина отображения (поиск по ev_width в хелпе). Фокс перед сравнением выполняет неявное округление. Посмотрите по ссылке Максимова пример

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
ln1 =  2 . 05 
ln2 =  100 
ln3 = ln1*ln2
ln4 =  205 
? STRCONV(BINTOC(ln3,"BR"), 15 )
? STRCONV(BINTOC(ln4,"BR"), 15 )
? ln3 = ln4
? ln3, ln4

получаем числа с разным внутренним представлением, числа по разному выводятся на экран, но сравнение их равно истине - см.рисунок
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37458281
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TЗапустить религия не позволила? vartype(x) вернет тип LOGICAL т.к. всем переменным объявленным в LOCAL присваивается .F., потому что написанное после AS игнорируется при выполнении.для неинициализированных переменых объявленный тип и впрямь не имеет значения. Пока они не инициализированы. А теперь запишите туда раунд(5,233648б2) и покажите вартайп.
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37458292
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Pavel09, запустил, есть погрешность. Похоже на точность влияет не только кол-во знаков после запятой, но и изначальное общее количество знаков. Как выше писал ROUND() лечит проблему:
Код: plaintext
if ROUND(n1-(n3-n2),  2 )* 10000000000  =  0 . 00  

Не знаю что твои числа означают, но если это деньги или что-то подобное по размерности, то подумай над использованием типа CURRENCY. Его придумали именно для тех случаев где даже малая погрешность недопустима в принципе. Конкретно в твоем примере замени и запусти:
Код: plaintext
n1 = $ 10000 
Реально CURRENCY это 8-мибайтовое целое у которого при отображении запятая сдвигается влево на 4 разряда, т.е. храниться целое количество десятитысячных долей, соответственно все минусы и особенности отсюда:
1. После каждой операции происходит округление до 4 знака, поэтому надо аккуратно делением пользоваться:
Код: plaintext
1.
2.
x = $ 12 . 34 
? x /  1000  *  100  &&  1 . 2300 
? x  *  100  /  1000  &&  1 . 2340 
2. При отображении без форматирования показывается 4 знака после запятой, поэтому приходится постоянно пользоваться форматированием если надо 2 знака после запятой.

Из плюсов: точность вычислений 18 знаков (больше будет ошибка переполнения), операции с CURRENCY выполняются немного быстрее чем с Numeric и Double.

Лично я предпочитаю тип CURRENCY если его допустимо применить. Некоторые разработчики его не любят (в первую очередь из-за особенности деления).
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37458295
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tanglirDima TЗапустить религия не позволила? vartype(x) вернет тип LOGICAL т.к. всем переменным объявленным в LOCAL присваивается .F., потому что написанное после AS игнорируется при выполнении.для неинициализированных переменых объявленный тип и впрямь не имеет значения. Пока они не инициализированы. А теперь запишите туда раунд(5,233648б2) и покажите вартайп.
Ничего не понял. Это к чему сказано?
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37459281
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima Ttanglirпропущено...
А теперь запишите туда раунд(5,233648б2) и покажите вартайп.
Ничего не понял. Это к чему сказано?К тому, что пока в переменной по умолчанию .F., то, конечно, вартайп вернёт L, это и ежу понятно. Но что вернёт вартайп, если в переменную заранее объявленного типа всё-таки записать значение, которое можно трактовать либо как объявленный тип, либо как какой-то другой. Вопрос-то в этом был, или я что-то пропустил?
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37459351
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tanglirDima Tпропущено...

Ничего не понял. Это к чему сказано?К тому, что пока в переменной по умолчанию .F., то, конечно, вартайп вернёт L, это и ежу понятно. Но что вернёт вартайп, если в переменную заранее объявленного типа всё-таки записать значение, которое можно трактовать либо как объявленный тип, либо как какой-то другой. Вопрос-то в этом был, или я что-то пропустил?
Пропустил, если вкратце, то была попытка доказать что "local x as doub" создает переменную типа DOUBLE. В хэлпе так написано:
MSDNLOCAL Command
Visual Studio .NET 2003
Creates local variables and variable arrays.

LOCAL Var1 [AS type [OF ClassLib]] ...

VarList
Specifies one or more local variables to create.
[ARRAY] ArrayName1 (nRows1 [, nColumns1]) [, ArrayName2 (nRows2 [, nColumns2])] ...
Specifies one or more local arrays to create. See DIMENSION for a description of each argument.
AS type
Specifies the data type on which this variable or array is based.
....
Оно и правда написано, только далее
MSDNRemarks
...
Variables and arrays created with LOCAL are initialized to false (.F.)...
Как хочешь так и понимай. Вобщем ерунды какой-то понаписали в хэлпе по поводу типизации переменных. Тут еще интересный опус: How to: Implement Strong Typing for Class, Object, and Variable Code
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37459372
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вобщем мое мнение: конструкция "AS ..." в фоксе нужна только чтобы подсказки выскакивали при наборе кода (свойства, методы объектов) и на работу кода она никак не влияет, т.е. при выполнении кода игнорируется.
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37461125
Фотография Игорь Горбонос
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
> Автор: Dima T
> Вобщем мое мнение: ...

Полностью разделяю это мнение.


Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37465488
nazinov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
автор> Автор: Dima T
> Вобщем мое мнение: ...

Полностью разделяю это мнение.
Аналогично!
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37466261
SSn888
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Давно не заглядывал на форум.... вот наворочено-то :)

Дима_Т, я не говорил ""local x as doub" создает переменную типа DOUBLE", тут у нас легкое недопонимание, из-за чего полагаю и возник сыр-бор.

local x as doub описывает переменную, которая _после_ придания ей корректного значения будет держать это значение как DOUBLE. Разница в нюансах.

А почему присваивает тип "поэкономней"... гм, потому что таков принцип фокса и не только его.. если по умолчанию присваивать наоборот, самые громоздкие типы - то рано или поздно начнуться проблемы.. например, с памятью.
Пример с такси показался Вам недостаточно наглядным? ;)
Или Вы наверно, везучий и по работе постоянно сталкиваетесь с новым железом и _не_ сталкивались с ситуацией "оперативка не более 256, причем половина ее уже забита всяким хламом"

"Вобщем мое мнение: конструкция "AS ..." в фоксе нужна только чтобы подсказки выскакивали при наборе кода (свойства, методы объектов) и на работу кода она никак не влияет, т.е. при выполнении кода игнорируется."...ээээ
мы на каких-то разных русских языках говорим, судя по всему :)
какие нафиг подсказки если речь идет о _переменных_?
Свойства и методы объектов касаются именно этих самых объектов, а какая подсказка по-Вашему должна вылезать при наборе переменной var1, объявленной как дубле? и в чем эта подсказка должна по-Вашему отличаться от переменной, объявленной AS INTEGER или AS еще много чего... Логика "для подсказок" сработает _только_ если объявляем AS Class...
Во всех остальных случаях AS для подсказок не может быть использован, потому что ПОДСКАЗЫВАТЬ НЕЧЕГО.
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37466322
XAndy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SSn888local x as doub описывает переменную, которая _после_ придания ей корректного значения будет держать это значение как DOUBLE. Разница в нюансах.

Чушь полная .
local x as double
абсолютно идентично
local x
и создает логическую переменную, никакую не double. И значение после as double этой переменной можно присвоить ЛЮБОГО ТИПА, хоть двадцать раз as double напишите. Потому что в фоксе динамическая типизация, а as double служит вовсе не для указания типа, как Вы думаете. Вы, похоже, фокс в глаза не видели :)
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37466346
SSn888
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
XAndy,
У Вас в Киеве всегда так принято слету хамить свысока или (надеюсь) - это только Вы такой выдающийся? Мне что - скан трудовой сюда со стажем вфп выложить? Окстись, не спеши судить свысока!

На вопрос "а зачем тогда возможность написать AS double", кстати - внятного ответа так и не получил ("для подсказки" не канает - см. выше)
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37466463
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SSn888Давно не заглядывал на форум.... вот наворочено-то :)

Дима_Т, я не говорил ""local x as doub" создает переменную типа DOUBLE", тут у нас легкое недопонимание, из-за чего полагаю и возник сыр-бор.

local x as doub описывает переменную, которая _после_ придания ей корректного значения будет держать это значение как DOUBLE. Разница в нюансах.

XAndy выше упоминал структуру ev_width , это и есть внутреннее хранение переменной в памяти:
MSDN Value Structure Definition// An expression's value.
Typedef struct {
char ev_type;
char ev_padding;
short ev_width;
unsigned ev_length;
long ev_long;
double ev_real;
CCY ev_currency;
MHANDLE ev_handle;
ULONG ev_object;
} Value;

Value Structure Fields

The following table is a guide to the values you can pass and receive in the Value structure for different types of data. Only the structure fields listed for a data type are used for that data type.

Contents of Value structure for different data types
Data typeStructure fieldValueNumericev_type'N'ev_widthDisplay widthev_lengthDecimal placesev_realDouble precision


Нет там нескольких типов для нецелых чисел, только DOUBLE

SSn888А почему присваивает тип "поэкономней"... гм, потому что таков принцип фокса и не только его.. если по умолчанию присваивать наоборот, самые громоздкие типы - то рано или поздно начнуться проблемы.. например, с памятью.
Я уже писал что не память надо экономить. Считаем:
65535 - максимально возможное количество переменных в фоксе (по умолчанию 16384)
8 байт - под хранение DOUBLE
т.е. под 65535 переменных DOUBLE надо 524280 байт, т.е. 0,5 Мб. Чего тут экономить?

SSn888Или Вы наверно, везучий и по работе постоянно сталкиваетесь с новым железом и _не_ сталкивались с ситуацией "оперативка не более 256, причем половина ее уже забита всяким хламом"
угу, есть еще вторые пни с W98 + 16Мб где действительно 6й фокс тормозит, правда стоит до 32Мб памяти добавить и все летает.

SSn888какие нафиг подсказки если речь идет о _переменных_?
Свойства и методы объектов касаются именно этих самых объектов, а какая подсказка по-Вашему должна вылезать при наборе переменной var1, объявленной как дубле? и в чем эта подсказка должна по-Вашему отличаться от переменной, объявленной AS INTEGER или AS еще много чего... Логика "для подсказок" сработает _только_ если объявляем AS Class...
Во всех остальных случаях AS для подсказок не может быть использован, потому что ПОДСКАЗЫВАТЬ НЕЧЕГО.
Немного истории фокса: в VFP6 (появился в 98м) подсказок не было и "AS" не было, после выхода SP5 мелкомягкие решили фокс похоронить, хоронили лет 5-6, потом неожиданно появилась 7-ка, следом в течении года 8-ка, в одной из которых это и появилось. Большая часть изменений были косметические, т.к. VFP6 имел устаревший вид прог под W95.
Т.е. по-твоему в платформе которая была создана под слабые компы в очередной версии добавили оптимизацию переменных? Кстати это совсем немаленькая доработка.

IntelliSence при подсказках пытается найти класс и вывести его свойства и методы, если не находит, то ничего не подсказывает.
Повторяю, то что после AS игнорируется при выполнении, простой пример:
Код: plaintext
1.
local x as supervar
x =  10 
Никаких ошибок не возникает, хотя другие языки дают ошибку в этом случае.

PS Не знаю как еще доказать отсутствие функционала, если ты считаешь что он все-таки есть - покажи пример кода при котором после добавления "AS ..." что-то изменится.
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37466859
SSn888
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T,

1) AS не влияет на функционал (твое утверждение, с которым, как вижу, есть достаточное количество согласных)
2) AS касаемо основных типов не служит для подсказки (см. выше)

И все-таки: А для чего тогда введено AS? В смысле - для чего оно введено для типов (с классами-то понятно)? Руководствуясь простой нормальной логикой - "если есть - значит для чего-то надо"...

И, пожалуйста, не надо столь подробных экскурсов в историю. Тут - излишне.
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37467128
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ХЗ почему так сделали, могу только свои предположения высказать:
1. Не факт что в хэлпе под data type подразумеваются простые типы, может под data type классы пользователя подразумеваются:
MSDNAS type
Specifies the data type on which this variable or array is based.
OF ClassLib
Specifies the class library containing the type description on which the type element of this variable or array is based.
Для базовых классов фокса можно без OF писать:
Код: plaintext
local x as timer
или где-то вначале подцепить библиотеку со своими классами (SET CLASSLIB TO MyLib), а потом на ее классы ссылаться без OF
Код: plaintext
local x as clsMy
это я к тому что невозможно проверить корректность написанного после AS т.к. SET CLASSLIB может быть не выполнена на момент правки кода.

2. Примечание (подсказка) разработчику какого типа задумана переменная. Хотя для решения этой проблемы с типами многие используют венгерскую нотацию.

Вобщем сделали это для классов и добавили игнорирование любых непонятных слов, как следствие получилось что после AS можно писать все что угодно.
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37467143
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SSn888И все-таки: А для чего тогда введено AS? В смысле - для чего оно введено для типов (с классами-то понятно)? Руководствуясь простой нормальной логикой - "если есть - значит для чего-то надо"...
Так Вам уже несколько раз объяснили. Это исключительно "дизайнерская" штука. В смысле, используется для раннего связывания на этапе написания программного кода. Не исполнения!

Ну, например, если написать так

Код: plaintext
LOCAL loExcel as Excel.Application

То потом, в тексте кода, если написать имя переменной loExcel и поставить точку, то отобразится выпадающий список свойств и методов объекта Excel (разумеется, если он был зарегестрирован). Без необходимости предварительного создания экземпляра Excel.

То же самое будет справедливо и для внутренних (пользовательских) классов FoxPro.

Однако, повторюсь, это действует только и исключительно на этапе разработки приложения "Design Time". На этапе исполнения кода (даже не в EXE, а просто для отладки) опция "as" - ничего не значит. Игнорируется.
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37467195
XAndy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SSn888это только Вы такой выдающийся?
Всё относительно ))))))))

Не понятно, почему Вам так трудно выполнить в среде разработки две строчки кода?
Код: plaintext
1.
2.
local x as double
? vartype(x)
или при отсутствии таковой поверить людям на слово, что as double НИЧЕГО не значит в runtime? 40 постов ради чего? Явный троллинг
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37467559
SSn888
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
XAndy,

я вообще-то не претендовал на роль святого :)

Тем не менее - "да, я был не прав в таком-то моменте" вовсе не означает "Да, Дмитрий прав".
Есть какой-то третий вариант.
Уже просто из спортивного интереса пытаюсь его нащупать... "Нахрена оно на самом деле"
Пока мало чего выходит, если найду - обязательно сюда тисну..

А насчет троллингов... Сударь, если Вам мерещаться гоблины или есть желание поругаться - обратитесь к зеркалу. Оно, падла, всегда покажет какой-нить прыщик :);)
Мне же лично просто доставляет удовольствие общение (пусть и не всегда.. ээ.. ровное) с людьми тут :)
...
Рейтинг: 0 / 0
Сравнение чисел double
    #37479345
:):):)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
задайте сами точность при сравнении
if abs(n1-n2)<0.0001
...
Рейтинг: 0 / 0
43 сообщений из 43, показаны все 2 страниц
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Сравнение чисел double
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]