Форум » [x]Harbour » Волшебные числа и операции » Ответить

Волшебные числа и операции

AndreyZh: Доброе утро! Вот наткнулся на очередную ошибку xHarbour и Clipper. Думал, что глюк ОС или ПК, но нет. Пример ошибки - оператор "остаток от деления": 8.8 * 3 = 26.4 или 3.3 * 3 = 9.9, но операции (%) дают 26.4%8.8 = 8.8 или (НО правильно) 9.9%3.3 = 0 Вопрос - как Вы обходите данные глюки? Или где в "арифметике" ожидать очередных "засад"? До кучи напомню об ошибочной работе функции Int в Clipper (в xHarbour кажется работает правильно)

Ответов - 136, стр: 1 2 3 4 5 6 7 All

AndreyZh: Доброе утро. Напишу много букф, т.к. исправление данного бага считаю важным и это проявляется в программе на Harbour, а на клиппере всё, правильно, как и должно быть .... Наверное не был услышан, но умею пользоваться шаблонами и etc. Более того понимаю Диму - попытался сделать самостоятельный пример и там всё работает правильно. Пример (иммитация логики программы): proc ptest() loca a:=" ", b:=" " cls @ 1,1 say "введите символы" get a @ 2,1 say "нажмите символ " get b read ptest2() retu proc ptest2() loca a:=" ", b:=" " @ 4,1 say "введите символы" get a @ 5,1 say "нажмите символ " get b read @ 6,0 say "нажмите клавишу "+b+" "+a inkey(0) retu Далее приведу реальный текст процедур, где ***** будут выделены ключевые моменты. Это один из десятков отчетов, где наблюдается данный глюк. Разбил на два сообщения, т.к. форум не хочет по русски воспринимать копипаст

AndreyZh: „P„‚„Ђ„t„Ђ„|„w„u„~„y„u. „Q„u„p„|„Ћ„~„Ђ„u „Ѓ„‚„y„|„Ђ„w„u„~„y„u... Всё конечно жутко понятно? ... попробую разделить на маленькое кусочки [pre2] * --------------------------------------------------------------------------- * Оборотная ведомость по финансовым операциям. Анализ кассы, банка по осно- * ваниям документов. * 03.2007 Доб. коррекцию начального сальдо. Работа по нескольким расч/счетам STAT PROC pObFins() LOCA cOldCol:=SetColor(), GetList:={}, dD:=Date(), dT:=Date(), nN:=0, nS:=0, cT:="" LOCA dBeg:=Date(), dEnd:=Date(), nPer:=1, nCash:=3, cReas:=Spac(15), nSaldo:=0 LOCA nBeg:=0, nEnd:=0, nPrih:=0, nRash:=0, np:=0, nr:=0 LOCA nStr:=99999, nPage:=0, nC:=0, nJ:=0, nRep:=77 LOCA cDbf:="", cNtx:="", cTxt:="" LOCA aArr:={{"dMove", "D", 8, 0},; {"sum", "N", 15, 2},; // Приход {"sumPut", "N", 15, 2}} // Расход LOCA sOp:="7655", cOff:=" " S_PROC cSent3 := Spac(25) // Из ЭФ читаем параметры построения отчета. fsWopen(16,18,7,59,cColor,2) @ 1,1 SAY "Пожалуйста вв. дату начала ........ конца ........ периода" @ 2,1 SAY "Цифру 1-Касса,2-Банк,3-Все . Длину подпериода(0-месяц) ..." @ 3,1 SAY "Набор букв основания документов или ничего ..............." @ 4,1 SAY "Набор букв сист.метки (F3) ........................." @ 5,1 SAY "Коррекция для начального сальдо по кассе/банку ..........." @ 6,1 SAY "Разделитель чисел для экспорта в MsOffice или ничего ." @1,28 GET dBeg VALI lValid({||dBeg<=Date()},"Больше текущей!") @1,43 GET dEnd VALI lValid({||dBeg<=dEnd},"Меньше начальной!") @2,28 GET nCash PICT "9" VALI Eval({||nSaldo:=IF(nCash=1,nCashSaldo,IF(nCash=2,nBankSaldo,nCashSaldo+nBankSaldo)),TRUE}) @2,56 GET nPer PICT "999" VALI lValid({||nPer>=0},"Отрицательная длина периода!") @3,44 GET cReas @4,34 GET cSent3 PICT "@S25" @5,48 GET nSaldo PICT "99999999.99" ***** Поведение зависит от введенного символа (глюки только, если точка или запятая) @6,58 GET cOff PICT "X" READ fDeact(cOldCol) cReas := Upper(Alltrim(cReas)) cSent3 := Upper(Alltrim(cSent3)) AP__INPUT ***** В принципе данная вставка решает проблему ****** изначально её не было и пока всё не переделал IF LastKey() == 44 .OR. LastKey() == 46 KEYB Chr(K_ENTER) Inkey(0) ENDI ******************************************** далее постороение отчета - некой вспомогательной таблицы // Настройка баз, расчет бегунка и т/д fTxt_act(" Пожалуйста подождите несколько минут!",cColor) nBeg := nSaldo SELE CASH_ORD ORDE CO_DAT_NUMBER IF nCash <> 2 COUNT TO nC WHIL dat <= dEnd ENDI SELE ACCOUNT ORDE A_DAT_NUMBER IF nCash <> 1 COUNT TO nN WHIL dat <= dEnd ENDI nC += nN cDbf := zTemp(cdTemp,"DBF",32) cNtx := zTemp(cdTemp,"NTX",32) cTxt := zTemp(cdTemp,"TXT",32) DbCreate(cDbf,aArr) LanUse("",cDbf,NO_INDEX,"TEMP",EXCL_MODE,-1,NEW_SEL) INDE ON dMove TO (cNtx) fDeact( cOldCol ) // Построение временной базы на основе первичных документов. pOpenView(cColor,cError,"Подождите! Строю оборотку по деньгам",TRUE) FOR nN := 1 TO 2 IF nCash == 1 .AND. nN == 2 THEN LOOP IF nCash == 2 .AND. nN == 1 THEN LOOP DbSelectArea( IF(nN=1,"CASH_ORD","ACCOUNT") ) DbGoTop() DO WHIL !Eof() .AND. dat <= dEnd pChangeView(++nJ*100/nC) IF Empty(datPay) THEN DbSkip(); LOOP IF !Empty(cReas) .AND. At(cReas,Upper(reason)) <= 0 THEN DbSkip(); LOOP IF !Empty(cSent3) .AND. At(cSent3,Upper(lab1)) <= 0 THEN DbSkip(); LOOP // Расчет начального сальдо. IF dat < dBeg nBeg += IF(tip=="1",(+1),(-1))*sum DbSkip() LOOP ENDI // Обработка операции. Добавляю при необходимости запись во времянку dD := dat nS := sum cT := tip SELE TEMP SEEK dD IF Eof() DbAppend() dMove := dD ENDI IF cT == "1" sum += nS ELSE sumPut += nS ENDI DbSelectArea( IF(nN=1,"CASH_ORD","ACCOUNT") ) DbSkip() ENDD NEXT nN ****** Отчет (таблица) преобразовывается в текстовый файл, который затем отражаю через набор устройств // Вывожу отчет в текстовый файл, считая итоги по подпериодам. SELE TEMP TOP dT := Max(dBeg,dMove) dD := Min(IF(nPer==0,Eom(dT),dT+nPer-1),dEnd) O____A ****** В принципе на эту верку попадаю, когда определяю знак разделитель в форме, но проверял в "обычных" вариантах - такая же херь IF !Empty(cOff) // Экспорт в офис ? "Оборотная ведомость по "+IF(nCash=1,"кассе",IF(nCash=2,"банку","деньгам"))+" с "+Dtoc(dBeg)+" по "+Dtoc(dEnd) ? " Подпериод времени Ост. на начало Приход Расход Ост.на конец " DO WHIL !Eof() X_DEMO IF dMove > dD // Перешли в другой подпериод. Отражаем итоги. ? IF(nPer==0,Left(zCmonth(dT)+Spac(17),17)+Str(Year(dT),4),Dtoc(dT)+" - "+Dtoc(dD))+" "+zStr(nBeg,14,2,cOff)+" "+zStr(np,12,2,cOff)+" "+zStr(nr,12,2,cOff)+" "+zStr(nBeg+np-nr,14,2,cOff) nBeg += np - nr np := nr := 0 dT := dMove dD := Min(IF(nPer==0,Eom(dT),dT+nPer-1),dEnd) ++nStr ENDI // Считаем параметры. np += sum nr += sumPut DbSkip() ENDD // Отражаю данные по последнему периоду и общие итоги. ? IF(nPer==0,Left(zCmonth(dT)+Spac(17),17)+Str(Year(dT),4),Dtoc(dT)+" - "+Dtoc(dD))+" "+zStr(nBeg,14,2,cOff)+" "+zStr(np,12,2,cOff)+" "+zStr(nr,12,2,cOff)+" "+zStr(nBeg+np-nr,14,2,cOff) ? Chr(12) *********** ELSE // Печатаемый формат DO WHIL !Eof() X_DEMO // Выводим шапку, если надо. IF nStr > nLenst IF nPage > 0 THEN Qout(Chr(12)) ? Padc("Оборотная ведомость по "+IF(nCash=1,"кассе",IF(nCash=2,"банку","деньгам"))+" с "+Dtoc(dBeg)+" по "+Dtoc(dEnd),nRep-7)+"Стр."+Str(++nPage,3) ? Repl("-",nRep) ? " Подпериод времени |Ост. на начало| Приход | Расход | Ост.на конец " ? Repl("-",nRep) nStr := 4 ENDI IF dMove > dD // Перешли в другой подпериод. Отражаем итоги. ? IF(nPer==0,Left(zCmonth(dT)+Spac(17),17)+Str(Year(dT),4),Dtoc(dT)+" - "+Dtoc(dD))+" "+cStr(nBeg,14,2)+" "+cStr(np,12,2)+" "+cStr(nr,12,2)+" "+cStr(nBeg+np-nr,14,2) nBeg += np - nr np := nr := 0 dT := dMove dD := Min(IF(nPer==0,Eom(dT),dT+nPer-1),dEnd) ++nStr ENDI // Считаем параметры. np += sum nr += sumPut nPrih += sum nRash += sumPut DbSkip() ENDD // Отражаю данные по последнему периоду и общие итоги. ? IF(nPer==0,Left(zCmonth(dT)+Spac(17),17)+Str(Year(dT),4),Dtoc(dT)+" - "+Dtoc(dD))+" "+cStr(nBeg,14,2)+" "+cStr(np,12,2)+" "+cStr(nr,12,2)+" "+cStr(nBeg+np-nr,14,2) ? Repl("-",nRep) ? Spac(36)+cStr(nPrih,13,2)+cStr(nRash,13,2) ? Chr(12) ENDI C____A pCloseView() ***************** Вывожу текстовый файл, используя отдельную процедуру печати, где по сути и проявляется данный глюк // Демонстрирую отчет и восстанавливаю состояние среды. pFileOutDevice(cTxt) pCloseErase("TEMP",{cDbf,cNtx,cTxt}) pinStat(sOp,0) RETU [/pre2]

AndreyZh: [pre2] PROC pFileOutDevice( cFile, nLen, nW, cdbfm ) FIEL compr, filen, begStr, endStr, qtyCopy LOCA nDev := ngOutDev LOCA nBeg := 1 // „N„p„‰„p„|„Ћ„~„p„‘ „ѓ„„„‚„p„~„y„?„p LOCA nEnd := 9999 // „K„Ђ„~„u„‰„~„p„‘ „ѓ„„„‚„p„~„y„?„p. LOCA nQty := 1 // „K„Ђ„|„y„‰„u„ѓ„„„r„Ђ „Џ„{„x„u„}„Ѓ„|„‘„‚„Ђ„r. LOCA cOldCol:=SetColor(), nSel:=Select(), cStr:="", aDbf:={}, cF:="" LOCA nSize:=FileSize(cFile), cString:="", GetList:={} LOCA nI:=0, cSt:="" LOCA axbk:={{"compr", "L", 1, 0},; {"filen", "C", 70, 0},; {"begStr", "N", 10, 0},; {"endStr", "N", 10, 0},; {"qtyCopy", "N", 10, 0}} PRIV cNameFile:="", cOutFile:="", lLoop:=TRUE DEFAULT nLen TO 80 DEFAULT nW TO 6 DEFAULT cdbfm TO "" MEMV->cNameFile := AllTrim(cFile) fSwopen(16,17,7,60,cOther,4) DO WHIL TRUE ******* Казалось бы читаем из обычной формы ввода, но Harbour ппосле её открытия нажимает некие клавиши, что даёт сразу вывод на устройство по умолчани. @ 5,0 SAY Chr(199)+Repl("„џ",59)+Chr(182) COLO PosRepl(cOther,Repl(" ",AT("/",cOther)-2)+"N",1) @ 1,2 SAY "„D„|„‘ „Ѓ„u„‰„p„„„y „Ђ„„„‰„u„„„p/„t„Ђ„{„…„}„u„~„„„p „Ѓ„Ђ„w„p„|„…„z„ѓ„„„p „…„{„p„w„y„„„u „…„ѓ„„„‚„Ђ„z„ѓ„„„r„Ђ" @ 2,2 SAY "1-„P„‚„y„~„„„u„‚,2-„U„p„z„|,3-„^„{„‚,4-„V„A„K,5-Exc„V„A„K,6-„Q„u„t„p„{„„„Ђ„‚,7-Word ." @ 3,2 SAY "„~„p„‰„p„|„Ћ„~„…„ђ „y „{„Ђ„~„u„‰„~„…„ђ „ѓ„„„‚„p„~„y„?„Ќ „y„x „t„Ђ„{„…„}„u„~„„„p" @ 4,2 SAY "„p „„„p„{„w„u „{„Ђ„|„y„‰„u„ѓ„„„r„Ђ „Џ„{„x„u„}„Ѓ„|„‘„‚„Ђ„r „Ѓ„u„‰„p„„„y „t„Ђ„{„…„}„u„~„„„p " @2,58 GET nDev PICT "9" VALI nDev>=1 .AND. nDev<=7 @3,12 GET nBeg WHEN nDev==1.OR.nDev==4 PICT "9999" VALI nBeg>=1 @3,30 GET nEnd WHEN nDev==1.OR.nDev==4 PICT "9999" VALI nBeg<=nEnd @4,56 GET nQty WHEN nDev==1.OR.nDev==4 PICT "999" VALI nQty>=1 READ ****** Это старая ошибка Harbour, которые разработчики уже исправили, но по своей глупой привычке использую свои обработки этого глюка /***** Смотреть как Lack будет реагировать на данный обработчик глюка. При этом появляется глюк Clipper - при прощелкивании Enter запросы идут по кругу, т.е. Ent не обрабатывается и переходим в обработку цикла */ IF lGlukHarb(nDev) THEN LOOP [/pre2]

AndreyZh: Добрый день! Системные программисты (разработчики), понимающие принципы "математики" xHarbour... ГДЕ ВЫ!!! Очередная пачка глюков данной системы разработки: 1. Деление и умножение обсудили раннее, а оказывается xharbour не умеет даже вычитать и складывать Сколько по Вашему будет (12.2 - 4.4 - 7.8) = ?, а теперь проверьте: WAIT Str((12.2 - 4.4 - 7.8)*1000000000,19,6) 2. Синтаксическая ошибка Wait "MAMA" * "PAPA" успешно пропускается компилятором, но программа вываливается по windows ошибке "too many recursive error handler calls"

Dima: AndreyZh пишет: Сколько по Вашему будет (12.2 - 4.4 - 7.8) = ?, Округляй результат. Clipper кстати так же отработал. ? (12.2 - 4.4 - 7.8)==0 // .F. ? round((12.2 - 4.4 - 7.8),2)==0 // .T.

Сыроежка: AndreyZh пишет: Сколько по Вашему будет (12.2 - 4.4 - 7.8) = ?, а теперь проверьте: Проверил! MS VC++ 2010: [pre2]if ( 12.2 - 4.4 - 7.8 == 0 ) std::cout << "equal to zero\n"; else std::cout << "not equal to zero\n"; std::cout << 12.2 - 4.4 - 7.8 << std::endl;[/pre2] Результат: not equal to zero -8.88178e-016

TimTim: AndreyZh пишет: Сколько по Вашему будет (12.2 - 4.4 - 7.8) = ? Это явление в вычислительной математике давно описано в учебниках по методам вычислений. Например, Бахвалов Н.С. Численные методы, М. 1975. В параграфе 4 "О вычислительной погрешности", в частности, автор пишет: "Здесь нам впервые встретилось явление потери значащих цифр (или "пропадания значащих цифр"), имеющее место при вычитании близких величин ...".

AndreyZh: Dima пишет: Округляй результат. Clipper кстати так же отработал. ? (12.2 - 4.4 - 7.8)==0 // .F. ? round((12.2 - 4.4 - 7.8),2)==0 // .T. На это считаю полезным отметить... заодно посмотрите результат Сыроежки... получаемая цифирь может быть, как больше, так и меньше нуля, кроме это вполне допустимы расчеты, где нормально, что результат "около нуля", т.е. банальные проверки типа "если имеется долг (сумма отгрузки - сумма платежей) клиента, то запретить ему отгрузку", а особенно если имеются скидки/наценки по накладной превращаются в громадные аналитические конструкции, где пытаешься отрабатывать, как "нормальные" погрешности округления, так и погрешности, связанные с логикой подгонки цифр в документах, так и с погрешностями "типа правильного счета" системы разработки. Просто замечу, что ни в клиппер, ни в фоксе, ни в си шарп, ни в аксес таких заморочек (на всей этой команде приходится пописывать) и "особенностей" не возникает, т.е. это не "математические особенности округления", а недоработки инструмента... в данном случае xharbour. Что по особенности Клиппер: а := 0.00 if a == 0.... Над этой ошибкой пришлось в древности много работать и учитывать, кроме того она по разному обрабатывается на разных ОС и разных типах процессоров. Вообще в данной темке "не обсираю" харб, а просто предупреждаю о возможных грабельках других раработчиков и если не интересно, то ...

Pasha: AndreyZh пишет: 1. Деление и умножение обсудили раннее, а оказывается xharbour не умеет даже вычитать и складывать Так мы ведь в прошлом году как раз вычитание и обсуждали, не ? Вот цитата от 22.09.11 18:58: Если "объяснения" по делению можно было как-то понять, то ошибки выитания (10000.00 - (21832.60 - 11832.60)) * 10000000000 = 0.018189894 (10000.00 - (21932.65 - 11932.65)) * 10000000000 = -0.018189894 (1.00 - (3.00 - 2.00) * 10000000000 = 0.0000 Я и тест делал, в котором видно, что примерно в 1/8 случаев при вычитании double fpu не дает ноль, или равенство. Для гарантированного получения нужного результата необходимо промежуточное округление. И харбор тут ни при чем, как и клиппер и любой другой язык, использующий явно или неявно тип double.

Pasha: AndreyZh пишет: Просто замечу, что ни в клиппер, ни в фоксе, ни в си шарп, ни в аксес таких заморочек (на всей этой команде приходится пописывать) и "особенностей" не возникает, т.е. это не "математические особенности округления", а недоработки инструмента... в данном случае xharbour. Как же не возникает, когда именно возникает именно такая же заморочка с клиппером. Дима же проверил. Да и я только что проверил. Насчет фокса мы когда-то выясняли, там имеется недокументированное неявное округление. О прочих инструментах говорить не буду.

PSP: Надо уже в Интел и АМД телегу писАть. Чё-та их ФПУ хреново складыватьумножатьвычитатьделить умеют... :)

Dima: По поводу фокса можно почитать тут

AndreyZh: Dima пишет: По поводу фокса можно почитать тут Доброе утро господа! Я не фоксист, не сишник, не и etc... Просто приходится зачастую использовать разный инструмент для решения конкретных задач. Все задачи связаны с бизнес расчетами и как следствие математика является основным нюансом на который обращают внимание пользователи. Как уже отмечал... не пытаюсь очень вникнуть во внутреннию топологию систем разработки. Все проблемки выявляют пользователи (по скромной оценке около 1000 человек) и ставят меня в известность... после чего пытаюсь найти источник проблемы и способ её исправления. Если пофилософствоать, то инструмент работы с базами или финансовой информацией должен в первую очередь обеспечивать стабильность работы с ней и "бухгалтерскую" точность (точность бухгалтерских расчетов). Если же в программе нужно также рассчитать траекторию полета спутника, то придется дописывать програмку на Си. Теперь по конкретным инструментам. Пока ещё в основном используется Clipper 5.01R + CTII и на его "методику" ориентируюсь в "сравнениях". На "вход" переделки под xharbour пошла программа отлаженная в течении 17 лет, в том числе отработаны "грабельки" данной версии клиппера, а тут оказывается не только есть "частичная" несовместимость языков, но и иные алгоритмы "математики". Лирика... на sql фоксисты рассуждают "куда податься с него" и получается, харбоур "тоже не вариант"? Хотя и имеет море предпосылок, что бы заменить все виды померших настольных СУБД. Что по "неумению считать" здесь озвучена идея "недокументированное неявное округление", наверное, что имело быть в пятом клиппере... а ведь это весьма разумно в бизнес приложениях. Под обсуждение арифметики как-то спрятались и другие "занятные" проблемки, озвученные выше: 1. Синтаксическая ошибка Wait "MAMA" * "PAPA" успешно пропускается компилятором, но программа вываливается по windows ошибке "too many recursive error handler calls" 2. Нелюбовь xHarbour к точке и запятой, в качестве переменной формы ввода.

Pasha: AndreyZh пишет: 1. Синтаксическая ошибка Wait "MAMA" * "PAPA" успешно пропускается компилятором, но программа вываливается по windows ошибке "too many recursive error handler calls" Что-то я не могу подтвердить такой результат. Компилятор и должен пропускать такую конструкцию, поскольку харбор язык с нестрогой типизацией. Это не синтаксическая ошибка, и клиппер это выражение тоже компилирует, как и харбор. А при его выполнении возникает ошибка "argument error", поскольку операция умножения для строк недопустима. "too many recursive error handler calls" - это уже результат работы обработчика ошибок. Стандартный обработчик ошибок xHarbour такое сообщение не дает. Возможно, у Вас он заменен своим. Смотрите свой обработчик ошибок.

PSP: AndreyZh пишет: то инструмент работы с базами или финансовой информацией должен в первую очередь обеспечивать стабильность работы с ней и "бухгалтерскую" точность (точность бухгалтерских расчетов). Откуда инструмент может знать, что программисту нужна "бухгалтерская" точность? Инструмент её обеспечивает, но только тогда, когда человек явно этого попросит.

Pasha: AndreyZh пишет: Что по "неумению считать" здесь озвучена идея "недокументированное неявное округление", наверное, что имело быть в пятом клиппере... а ведь это весьма разумно в бизнес приложениях. Ничего не понятно. Клиппер 5.01, который Вы используете, при операциях с double ведет себя точно так же, как и харбор. Никакого недокументированного округления там и в помине нет. Так зачем его вводить в харборе ? Тогда харбор будет вести себя не так, как клиппер. В ваших примерах клиппер и харбор дают одинаковый результат. Можете дать пример, в котором они ведут себя по разному ? С клиппером у вас дожны были быть такие же заморочки, как и с харбором. Но с клиппером почему-то это проблемы не создавало, а с харбором начало создавать ? Или просто на клиппер некому было пожаловаться ? :)

AndreyZh: Pasha пишет: AndreyZh пишет: цитата: 1. Синтаксическая ошибка Wait "MAMA" * "PAPA" успешно пропускается компилятором, но программа вываливается по windows ошибке "too many recursive error handler calls" Что-то я не могу подтвердить такой результат. Компилятор и должен пропускать такую конструкцию, поскольку харбор язык с нестрогой типизацией. Это не синтаксическая ошибка, и клиппер это выражение тоже компилирует, как и харбор. А при его выполнении возникает ошибка "argument error", поскольку операция умножения для строк недопустима. "too many recursive error handler calls" - это уже результат работы обработчика ошибок. Стандартный обработчик ошибок xHarbour такое сообщение не дает. Возможно, у Вас он заменен своим. Смотрите свой обработчик ошибок. Использую редакцию xHarbour 1.2.1 rev 6633... по обработчикам ошибок не пугайте такими словами (шутка). Ругается не харб, а судя по win окнам сами винды... Смотрите:

PSP: AndreyZh пишет: Ругается не харб, а судя по win окнам сами винды... Нет, это не винда, а именно хХ. Обработчик ошибок зациклился на вызовах самого себя.

AndreyZh: PSP пишет: Откуда инструмент может знать, что программисту нужна "бухгалтерская" точность? Инструмент её обеспечивает, но только тогда, когда человек явно этого попросит. А что... какой результат можно попросить от операции 12.2 - 4.4 - 7.8? Теперь... от куда данные цифры. Есть операция распределения товаров накладной по нескольким складам (отделам магазина). В данном случае пришло 12.2 кг. товара, где в первый отдел нужно определить 4.4 кг, а во второй 7.8. Бедный оператор соглашается с числом 7.8, а прога в ответ не могу.... блок программы уже с извращениями (исправлениями): [pre2] nMax := qtyAll fSwopen(21,0,3,79,cOther,2) DO WHIL !Eof() .AND. codInv==cInv // Читаем распределение по конкретному складу и товару. cCodStores := Spac(2) nQty := nMax @ 1,1 SAY WARES->name+" Осталось распред."+Str(nMax,10,3) @2,1 SAY "Распределить на склад:" GET cCodStores VALI Eval(bCodStores,cCodStores) .AND. Eval({||DevPos(2,28),DevOut(HB_STORE->shotName,cOther),TRUE}) @2,56 SAY "Количество:" GET nQty PICT "9999999.999" VALI lValid({||nQty>=0.AND.nQty<=nMax+0.000001},"Неверное кол-во. Отрицательно или слишком большое!") .AND. zlWar(DETALREC->codWares,nQty) READ IF LastKey()==K_ESC lBreak := TRUE; EXIT ENDI /* Запоминаем данные в массиве и меняем настройки. Склад может повторится, в этом случае добавляем количество в туже строку */ lArr := TRUE FOR nI := 1 TO Len(aArr) IF aArr[nI,1]==DETALREC->codWares.AND.aArr[nI,2]==cCodStores lArr := FALSE; EXIT ENDI NEXT nI IF lArr // Новый товар и склад. Aadd(aArr,{DETALREC->codWares,cCodStores,nQty,DETALREC->sales,DETALREC->tax_n,DETALREC->tax_s}) ELSE // Имеется строка в массиве. aArr[nI,3] += nQty ENDI nMax -= nQty // Еще не весь товар текущего наименования распределили. IF nMax > 0 THEN LOOP DbSkip() nMax := qtyAll ENDD[/pre2] А заодно отвечаю на: Pasha пишет: С клиппером у вас дожны были быть такие же заморочки, как и с харбором. Но с клиппером почему-то это проблемы не создавало, а с харбором начало создавать ? Или просто на клиппер некому было пожаловаться ? :) Этот блок использовался без изменения уже больше 20 лет... еще и системы не было... а операция "распределения" производится (провожу ежегодный анализ) более 50 000 раз по всем клиентам (или перебирают больше 200 000 комплектов цифр ежегодно)... была бы проблема - давно бы наткнулся. На xHarb она поперла в виде звонков ежедневно, как начал переводить розничные магазины.

PSP: AndreyZh пишет: А что... какой результат можно попросить от операции 12.2 - 4.4 - 7.8? _SET_DECIMALS в какое значение установлен? Может поменьше сделать, а? Ты уж определись, какая точность тебе нужна. Не думаю, что при расчете масс, сумм, количеств нужна точность в 10 знаков.



полная версия страницы