InterBase & типа FLOAT
13 отговора
176 прегледа
InterBase & типа FLOAT
C++ & Delphi
проблема е следния :
имам таблица X в която имам поле Y от тип FLOAT
при присвояване
....
S = "0.3249";
IBStoredProc->Params->Items[y]->AsFloat = StrToFloat(S);
...
в базата се записва числото 0.32490000128746
т.е. не се нулират последните 6 позиции в числото и при по нататашни изчисления имам проблем с точноста.
Някой има ли идея как се нулират тези послени позиции или как изобщо се решава този проблем.
благодаря предварително.
проблема е следния :
имам таблица X в която имам поле Y от тип FLOAT
при присвояване
....
S = "0.3249";
IBStoredProc->Params->Items[y]->AsFloat = StrToFloat(S);
...
в базата се записва числото 0.32490000128746
т.е. не се нулират последните 6 позиции в числото и при по нататашни изчисления имам проблем с точноста.
Някой има ли идея как се нулират тези послени позиции или как изобщо се решава този проблем.
благодаря предварително.
Re: InterBase & типа FLOAT
Ако искаш да работиш с числа с фиксирана точност ползвай NUMERIC()

Re: InterBase & типа FLOAT
С NUMERIC нещата са още по зле защото при заявка :
..
X NUMERIC(15,6)
Y NUMERIC(15,6)
...
SELECT X * Y
...
се получава велик резултат от вида 14325245.31254
и спасението е SELECT CAST(X * Y AS FLOAT)
.....
но не си е работа....ако ме разбираш... :))))))))
..
X NUMERIC(15,6)
Y NUMERIC(15,6)
...
SELECT X * Y
...
се получава велик резултат от вида 14325245.31254
и спасението е SELECT CAST(X * Y AS FLOAT)
.....
но не си е работа....ако ме разбираш... :))))))))
Re: InterBase & типа FLOAT
От Что НЕ надо делать
20. Не надо использовать тип FLOAT
этот тип данных имеет длину 4 байта и точность всего 7 цифр. Эквивалентом в Delphi является single. Если хотите использовать вещественные числа, то сначала попробуйте перемножить и поделить два таких числа прямо в Delphi - так вы увидите точность вычислений, что исключит впоследствии проблемы с хранением и обработкой таких данных в базе.
вж. също
[линк]
[линк]

20. Не надо использовать тип FLOAT
этот тип данных имеет длину 4 байта и точность всего 7 цифр. Эквивалентом в Delphi является single. Если хотите использовать вещественные числа, то сначала попробуйте перемножить и поделить два таких числа прямо в Delphi - так вы увидите точность вычислений, что исключит впоследствии проблемы с хранением и обработкой таких данных в базе.
вж. също
[линк]
[линк]
Редактирано от NDeu на
Re: InterBase & типа FLOAT
ВСИЧКО ДОБРЕ НО!!!!!
ТБЛИЦА STOR;
//всички полета от NOMQNT1 до NOMPRICE3 са от тип NUMERIC(15,6)
IDSTOR | IDNOM | NOMQNT1 | NOMQNT2 | NOMQNT3 | NOMPRICE1 | NOMPRICE2 | NOMPRICE3
1 | 1 | 9 | 5 | 4 | 0.3 | 0.5 | 0.3
ПРИ UPDATE В КОНЗОЛАТА ИЛИ ЧРЕЗ IBQUERY :
=======================
UPDATE STOR
SET NOMQNT2 = NOMQNT2 + 5,
NOMPRICE3 = FORMATFLOAT( ( (NOMQNT1 + NOMQNT2 - NOMQNT3)*NOMPRICE3 + (5 * 0.43))/
((NOMQNT1 + NOMQNT2 - NOMQNT3)+5),4
),
NOMPRICE1 = 0.43
=======================
СЕ ПОЛУЧАВА РЕЗУЛТАТ NOMPRICE3= 0.3325 ?!?!?!?!?!?!?
<<<<<<<<<<>>>>>>>>>>>>>>
А ПРИ SELECT :
==================
select FORMATFLOAT( ( (NOMQNT1 + NOMQNT2 - NOMQNT3)*NOMPRICE3 +
(5 * 0.43)
)/((NOMQNT1 + NOMQNT2 - NOMQNT3)+5),4)
FROM STOR
==================
СЕ ПОЛУЧАВА РЕЗУЛТАТ 0.3433 КОЕТО Е КОРЕКТНИЯ РЕЗУЛТАТ !!!!!
дори и без използването на FORMATFLOAT положението е същото???
НЯКОЙ ЗНАЕ ЛИ ЩО ЗА ФЕНОМЕН Е ТОВА????
Всичко е зле когато завършва ЗЛЕ.
ТБЛИЦА STOR;
//всички полета от NOMQNT1 до NOMPRICE3 са от тип NUMERIC(15,6)
IDSTOR | IDNOM | NOMQNT1 | NOMQNT2 | NOMQNT3 | NOMPRICE1 | NOMPRICE2 | NOMPRICE3
1 | 1 | 9 | 5 | 4 | 0.3 | 0.5 | 0.3
ПРИ UPDATE В КОНЗОЛАТА ИЛИ ЧРЕЗ IBQUERY :
=======================
UPDATE STOR
SET NOMQNT2 = NOMQNT2 + 5,
NOMPRICE3 = FORMATFLOAT( ( (NOMQNT1 + NOMQNT2 - NOMQNT3)*NOMPRICE3 + (5 * 0.43))/
((NOMQNT1 + NOMQNT2 - NOMQNT3)+5),4
),
NOMPRICE1 = 0.43
=======================
СЕ ПОЛУЧАВА РЕЗУЛТАТ NOMPRICE3= 0.3325 ?!?!?!?!?!?!?
<<<<<<<<<<>>>>>>>>>>>>>>
А ПРИ SELECT :
==================
select FORMATFLOAT( ( (NOMQNT1 + NOMQNT2 - NOMQNT3)*NOMPRICE3 +
(5 * 0.43)
)/((NOMQNT1 + NOMQNT2 - NOMQNT3)+5),4)
FROM STOR
==================
СЕ ПОЛУЧАВА РЕЗУЛТАТ 0.3433 КОЕТО Е КОРЕКТНИЯ РЕЗУЛТАТ !!!!!
дори и без използването на FORMATFLOAT положението е същото???
НЯКОЙ ЗНАЕ ЛИ ЩО ЗА ФЕНОМЕН Е ТОВА????
Всичко е зле когато завършва ЗЛЕ.
Re: InterBase & типа FLOAT
Ами много просто - това не е феномен. Защо използваш FormatFloat и сигурен ли си, че някъде там не ти се объркват нещата? Изкарай си междинните резултати и виж къде ти се закръгля. Защо изобщо тези сметки ги правиш в SQL? Уверявам те, че в програмата също могат да се сметнат. Освен това изпълнения от вида s := '1.23456'; f := StrToFloat(s); нито са производителни, ното са точни. Не ти гарантирам, че StrToFloat ще ти върне 1.23456 а не примерно 1.2345597534232 или нещо такова...
Re: InterBase & типа FLOAT
1. Този ФЕНОМЕН показва, че при update нe се гарантира изолираност на операциите.
След
NOMQNT2 = NOMQNT2 + 5,
в израза
NOMPRICE3 = ( (NOMQNT1 + NOMQNT2 - NOMQNT3)*NOMPRICE3 + (5 * 0.43))/((NOMQNT1 + NOMQNT2 - NOMQNT3)+5)
NOMQNT2 вече участва с новата си стойност.
Размени местата на NOMQNT2 и NOMPRICE3 в update-то и ще получиш каквото ти трябва.
2. Не препоръчвам използването на FORMATFLOAT в този случай. Просто не е необходимо
3. Не е добър стил ДА КРЕЩИШ ПО ФОРУМИТЕ. Говори за склонност към истерия
Пък и трудно се чете
Успех

След
NOMQNT2 = NOMQNT2 + 5,
в израза
NOMPRICE3 = ( (NOMQNT1 + NOMQNT2 - NOMQNT3)*NOMPRICE3 + (5 * 0.43))/((NOMQNT1 + NOMQNT2 - NOMQNT3)+5)
NOMQNT2 вече участва с новата си стойност.
Размени местата на NOMQNT2 и NOMPRICE3 в update-то и ще получиш каквото ти трябва.
2. Не препоръчвам използването на FORMATFLOAT в този случай. Просто не е необходимо
3. Не е добър стил ДА КРЕЩИШ ПО ФОРУМИТЕ. Говори за склонност към истерия
Успех
Re: InterBase & типа FLOAT
andrew.....
не съм съгласен с теб !!!
т.е. << Защо изобщо тези сметки ги правиш в SQL? >>
Според теб защо изобщо съществува SQL ако не се използва едно от най силните му преимущества да спестиш 70% код от сметки!!!
//и това разбира се не е всичко но не мисля да споря на тази тема :)))
А и какъв е смилсъла да използвам SQL само за банка-данни
все пак благодаря за съдейтвието..
не съм съгласен с теб !!!
т.е. << Защо изобщо тези сметки ги правиш в SQL? >>
Според теб защо изобщо съществува SQL ако не се използва едно от най силните му преимущества да спестиш 70% код от сметки!!!
//и това разбира се не е всичко но не мисля да споря на тази тема :)))
А и какъв е смилсъла да използвам SQL само за банка-данни
все пак благодаря за съдейтвието..
Re: InterBase & типа FLOAT
Very very 10x NDeu....
Разбира се почти винаги грешката е в питащия...
Наистина се оказа че "РЕДА" на изпълнение в UPDATE има значение което аз до сега не го знаех...
Относно крещенето .... не е точно това което си "видял"...:)))
част от навиците ми, е да пиша с големи букви... но не че не виждам и не че крещя... а просто навик...
// и аз не обичам да пушат около мен защото нямам навика да пуша :))))
Още веднъж много благодаря за помоща ти защото ми беше вери спешъл.....
но има още един не толкова "BIG" проблем...
========
X NUMERIC(15,6); //5
Y NUMERIC(15,6); // 0.43
заявка в QUERY :
SELECT X * Y ми връща 2 955.8141
а при
SELECT CAST(X * Y AS FLOAT) ми връща 2.1500 //което е вярното...
10x
Разбира се почти винаги грешката е в питащия...
Наистина се оказа че "РЕДА" на изпълнение в UPDATE има значение което аз до сега не го знаех...
Относно крещенето .... не е точно това което си "видял"...:)))
част от навиците ми, е да пиша с големи букви... но не че не виждам и не че крещя... а просто навик...
// и аз не обичам да пушат около мен защото нямам навика да пуша :))))
Още веднъж много благодаря за помоща ти защото ми беше вери спешъл.....
но има още един не толкова "BIG" проблем...
========
X NUMERIC(15,6); //5
Y NUMERIC(15,6); // 0.43
заявка в QUERY :
SELECT X * Y ми връща 2 955.8141
а при
SELECT CAST(X * Y AS FLOAT) ми връща 2.1500 //което е вярното...
10x
Re: InterBase & типа FLOAT
Не знам защо си мислиш, че ще спестиш 70% код от сметки, когато изнесеш сметките от по-високопроизводителна система като компилираната ти програма на делфи, в SQL заявката ти, която определено се изпълнява по-бавно, определено се поддържа по-трудно и определено като гледам ти е доста децентрализирана...
Много по-ясно и по-продуктивно, а и значително по-универсално за теб (а и от там по-кодоспестяващо) ще е вместо
UPDATE STOR
SET NOMQNT2 = NOMQNT2 + 5,
NOMPRICE3 = FORMATFLOAT( ( (NOMQNT1 + NOMQNT2 - NOMQNT3)*NOMPRICE3 + (5 * 0.43))/
((NOMQNT1 + NOMQNT2 - NOMQNT3)+5),4
),
NOMPRICE1 = 0.43
да си напишеш
update stor set
nomqnt1 = :nomqnt1,
nomqnt2 = :nomqnt2,...
и да си използваш сметките в ехе-то или поне в сторедпроцедура, отколкото да пишеш магически изрази като горния, които дори ти не успя да разбереш какво всъщност вършат.
А по-въпроса за или против използването на SQL само за банка-данни (предполагам всъщност имаш предвид ползването на базата данни само за банка данни, защото не виждам как можеш да съхраниш каквито и да е данни в SQL) - бизнес логиката не се съхранява в базата данни под формата на SQL заявки, записани в пропъртитата на Query-то ти е делфи, а като сухранени процедури, тригери и други подобни неща в самата база например...
Много по-ясно и по-продуктивно, а и значително по-универсално за теб (а и от там по-кодоспестяващо) ще е вместо
UPDATE STOR
SET NOMQNT2 = NOMQNT2 + 5,
NOMPRICE3 = FORMATFLOAT( ( (NOMQNT1 + NOMQNT2 - NOMQNT3)*NOMPRICE3 + (5 * 0.43))/
((NOMQNT1 + NOMQNT2 - NOMQNT3)+5),4
),
NOMPRICE1 = 0.43
да си напишеш
update stor set
nomqnt1 = :nomqnt1,
nomqnt2 = :nomqnt2,...
и да си използваш сметките в ехе-то или поне в сторедпроцедура, отколкото да пишеш магически изрази като горния, които дори ти не успя да разбереш какво всъщност вършат.
А по-въпроса за или против използването на SQL само за банка-данни (предполагам всъщност имаш предвид ползването на базата данни само за банка данни, защото не виждам как можеш да съхраниш каквито и да е данни в SQL) - бизнес логиката не се съхранява в базата данни под формата на SQL заявки, записани в пропъртитата на Query-то ти е делфи, а като сухранени процедури, тригери и други подобни неща в самата база например...
Re: InterBase & типа FLOAT
Казах че не искам да влизам този спор за SQL и сметки но се изкушавам да ти отговоря :
БЕСПОРНО :
========
update stor set
nomqnt1 = :nomqnt1,
nomqnt2 = :nomqnt2,...
========
е много по кратко но как се стига до :nomqnt1 и :nomqnt2 не си написал...
не се имам за велик програмист но аз разполагам с едно ID и два параметъра ":nomqnt1/2" и си свършвам работата само с една заявка ... а иначе ако се придържам към твоя съвет трябва да направя следното
1.Да извлека полетата които ми трябват за сметката със заявка...
т.е ( NOMQNT1/2/3 ,, NOMPRICE1/3 )
2.Да си декларирам още n променливи за горните полета
3. Да натоваря клиентския процесор със сметки вместо сървъра
// според мен идеята е сървъра да се товари и се предполага че клиента е слаб //
4.Да направя нова заяква за UPDATE
// до тук комуникациите станаха 2 ...
Не мисля че някой от нас двамата е по ПРАВ защото всеки си има стил и виждане за програмиране но ще се радвам да науча и нещо ново от теб...
и все пак аз все още преоткривам SQL-а така че ако греша ще се радвам да ме поправите....:)))
БЕСПОРНО :
========
update stor set
nomqnt1 = :nomqnt1,
nomqnt2 = :nomqnt2,...
========
е много по кратко но как се стига до :nomqnt1 и :nomqnt2 не си написал...
не се имам за велик програмист но аз разполагам с едно ID и два параметъра ":nomqnt1/2" и си свършвам работата само с една заявка ... а иначе ако се придържам към твоя съвет трябва да направя следното
1.Да извлека полетата които ми трябват за сметката със заявка...
т.е ( NOMQNT1/2/3 ,, NOMPRICE1/3 )
2.Да си декларирам още n променливи за горните полета
3. Да натоваря клиентския процесор със сметки вместо сървъра
// според мен идеята е сървъра да се товари и се предполага че клиента е слаб //
4.Да направя нова заяква за UPDATE
// до тук комуникациите станаха 2 ...
Не мисля че някой от нас двамата е по ПРАВ защото всеки си има стил и виждане за програмиране но ще се радвам да науча и нещо ново от теб...
и все пак аз все още преоткривам SQL-а така че ако греша ще се радвам да ме поправите....:)))
Re: InterBase & типа FLOAT
А прочете ли частта за съхранените процедури?
CREATE PROCEDURE UPDATE_STORE_WITH_NEW_QUANTITY(StoreID Integer, NewQuantity Double Precision)
AS
BEGIN
....
На това се вика бизнеслогика в базата... 1 комуникация.... 1 място.... Лесна поддръжка...
CREATE PROCEDURE UPDATE_STORE_WITH_NEW_QUANTITY(StoreID Integer, NewQuantity Double Precision)
AS
BEGIN
....
На това се вика бизнеслогика в базата... 1 комуникация.... 1 място.... Лесна поддръжка...
Re: InterBase & типа FLOAT
>SELECT X * Y ми връща 2 955.8141
Грешката е на клиента, който ползваш (вероятно IBConsole). Физическото представяне на този тип е Int64, а по-старите клиенти не умеят да работят добре с него.
Workaround:
1. За да нямаш подобни проблеми cast-вай до char. Тогава интерпретирането го прави сървъра, а клиента си работи само със символи.
2. Смени си клиента. На мен ми допада IB Expert.

Грешката е на клиента, който ползваш (вероятно IBConsole). Физическото представяне на този тип е Int64, а по-старите клиенти не умеят да работят добре с него.
Workaround:
1. За да нямаш подобни проблеми cast-вай до char. Тогава интерпретирането го прави сървъра, а клиента си работи само със символи.
2. Смени си клиента. На мен ми допада IB Expert.
Re: InterBase & типа FLOAT
Ок .
имам и двата клиента и също предпочитам братушките
но в момента съм с конзолата и забелязвам че се пръкват тук там и други бъгчета :)))
ше направим един drop на конзолата...
10x
имам и двата клиента и също предпочитам братушките
но в момента съм с конзолата и забелязвам че се пръкват тук там и други бъгчета :)))
ше направим един drop на конзолата...
10x