-
Уважаемые Мастера! Первый раз с таким столкнулся и вполном замешательстве... В таблице: PoleCena : Float = 2,5 PoleKol : Float = 0,046 PoleSumma : Float (Calculated) := Round(PoleCena*PoleKol*100)/100
Комп1: PoleSumma = 0,12 Комп2: PoleSumma = 0,11 Комп3: PoleSumma = 0,11
Программа установлена на Комп1. На комп2 и Комп3 запускается по сети. Комп1 и Комп2 абсолютно одинаковые (покупались в один день с одинаковыми версиями винды и с тех пор не переустанавливалась). На моем копьютере PoleSumma = 0,11 Это что?
-
> DimDim (10.11.2008 12:02:00) [0]
Это может какая ни будь программа, которая меняет маску.
-
Причем здесь маска? Я программно округляю до 2-х знаков после запятой. Программа, меняющая математику процессора? Компьютер - это усовершенствованый калькулятор. Как можно поменять в принципе незыблимые в природе законы математики? Я понимаю, что для компьютера 2*2 = примерно 4. Но законы округления на едентичных машинах должны быть одинаковые...
-
> DimDim
Программа твоя ?
Тогда непосредственно перед вызовом Round вызови GetRoundMode и посмотри режим округления
-
Программа моя. Закзчик (где эта х... проявилась) далековато. С GetRoundMode ниразу не сталкивался. Что она дает? Можно поподробней? Да и толку что я узнаю режим округлений? Бороться с этим как?
-
> Закзчик ..далековато.
Это твоя личная драма.
> Что она дает? Можно поподробней?
см. справку, там все написано.
> толку что я узнаю режим округлений?
Как минимум подтвержишь или опровергнешь факт того, что разные экз-ры твоей программы на разных машинах используют при округлении разные его режимы, из-за чего отличаются результаты округления
-
Да и мне, собственно, по барабану в какую сторону она 5 округляет - лижбы у всех одинаково округляла...
-
> лижбы у всех одинаково округляла
Тогда проверяй региональные установки у каждого пользователя.
-
> DimDim (10.11.2008 13:01:04) [4]
www.intel.com архитектура процессора.
-
> DimDim (10.11.2008 13:09:06) [6]
Тогда обеспечить у всех одинаковую среду
-
Ну, про региональные установки - это первое что пришло на мысль. Но там ведь нихр... похожего нет. Да и быть не может. Даже в африке 2*2=4. Если какая-то настройка и есть, то где-то на уровне биоса.
> Тогда обеспечить у всех одинаковую среду Пользуется программой 400 заказчиков (около 1000 компов). ИЗДЕВАЕТЕСЬ???
Попробую переписать процедуры округлений в такой вид: Round((PoleCena*PoleKol*100)+0.0000000000000001)/100 может поможет. Буду надеяться, что это не повлияет на другие вычисления.
Но все равно это не правильно! У меня в корне подорвана вера в вычислительную технику! Один и тот же расчет, сделаный на разных компах может дать разные результаты? Бред...
-
> DimDim (10.11.2008 22:26:10) [10]
Бред, при одинаковых условиях - результаты одинаковые.
-
Какие нах... условия в элементарной математике!??? Или может от каких-то условий теорема Пифагора может поменяться?
Я сам свято верил что такого быть не может! Пока мне заказчики пальцем не показали.
-
> DimDim (11.11.08 01:28) [12]
И чего ты разнахался ?) Не трожь элементарную математику - в ней еще и не такие чудеса происходят) Вот тебе пища для размышления:
procedure TForm1.Button1Click(Sender: TObject);
type
const
PoleCena : Float = 2.5;
PoleKol : Float = 0.046;
var
PoleSumma: Float;
begin
PoleSumma := Round(PoleCena*PoleKol*100)/100;
ShowMessage('Результат без маски: ' + FloatToStr(PoleSumma) + ' , Результат с маской: ' + FormatFloat('# ##0.00', PoleSumma));
end;
Удивись и задумайся над тем ЧТО на самом деле есть Float-тип поля дейтасета на каждом из рассматриваемых тобой компах)
-
Все это понятно. И наглядней это будет так: procedure TForm1.Button1Click(Sender: TObject);
type
Float = Single; const
PoleCena : Float = 2.5;
PoleKol : Float = 0.046;
var
PoleSumma: Float;
begin
Label1.Caption:=FloatToStr(PoleCena);
Label2.Caption:=FloatToStr(PoleKol);
PoleSumma := Round(PoleCena*PoleKol*100)/100;
Label3.Caption:='Результат без маски: ' + FloatToStr(PoleSumma) +
' , Результат с маской: ' + FormatFloat('# ##0.00', PoleSumma);
end; И ты хочешь сказать, что "Результат без маски" на разных компьютерах может <> 0,119999997317791 из-за каких-то настроек? Ну, я бы мог это понять, если бы один и тот расчет выполнялся в разных вариантах программы с разными типами переменных. В принципе, очень поучительный пример с точки зрения общей теории. А делать-то чаво? Узнал от заказчика много интересного о себе... Их теория не интересует - их интересует достоверность расчета.
-
Я хочу сказать только одно : видимый результат (с маской или без маски - индифферентно) так или иначе зависит от формата хранения и представления чисел с п/з - как операндов, так и результата.
Вероятно, следует сосредоточиться на исследовании среды функционирования СУБД, с которой работает твоя программа - именно она поставляет для TFloatField-операндов данные в формате чисел с п/з . Один клиент получает их в виде Single-типа и видит в результате дальнейших вычислений один результат, а другой клиент получает, скажем, Double-тип и видит, как ты уже убедился, другой результат.
> Узнал от заказчика много интересного о себе
И он прав - ты как разработчик должен был предвидеть такую ситуацию .. или же принять меры к идентичности СУБД-среды
-
> DimDim (11.11.2008 12:17:14) [14]
Не настроек, а масок процессора - контрольное слово процессора. Обычное дело, из-за твоего коды ты обязан был рано или позно попасть, поскольку код предполагает эту "ошибку". Нафиг делать такое кривое округление до двух, которое к тому же бессмысленно без маски вывода в f-FormatFloat поскольку float это число с плавающей запятой и системе глубоко пофиг на твои изращения. Почитай на Королевстве, что это такое.
-
Я отлично понимаю что такое число с плавающей точкой и почему одно и то же число в разных типах переменных не равны. "Такое кривое округление" делается не от хорошей жизни, а потому что от результата делается еще мульен вычислений. Причем, в расчетах он печатается как промежуточный. Отображать через маску не округленный результат - тогда лажа (точнее - не понятные заказчику числа) вылазят в дальнейшем расчете. Программа по расчету сметной стоимости строительства. Конечные расчеты (сметы, акты и т.д.) проверяются двумя сторонами - кто их составляет и для кого они составляются. Проверяют обычно от одного промежуточного результата до другого. ПРОВЕРЯЮТ КАЛЬКУЛЯТОРОМ! И при проверке смотрят на промежуточные результаты ИЗ РАСПЕЧАТКИ. Каждому не объяснишь что в распечатке предполагаются точные числа. А уж тем более что на одном компе посчитано с точностью Extended, а на другом, почему-то, с точность Single. Поэтому КАЖДЫЙ промежуточный результат (который выводится в распечатки) приходится явным образом округлять, чтобы избежать лишних вопросов. Я уже молчу, что в программе предусмотрена пользовательская система настройки точности вычислений... Если бы результат округления был бы некий конечный результат, который распечатать и забыть - то проблемы бы небыло - однозначно FormatFloat.
-
> DimDim (12.11.2008 0:34:17) [17]
Но в твоих примерах, не в расчете, а простой вывод на метку. Если нужна абсолютная точность, то надо использовать точные, а не приблизительные числа, не Float, а BCD, в крайнем случае Currency. Но ведь и в этом случае операции не коммутативны. A/B * B <> A, попробуй 1/2*3 c промежуточными результатами. Расчеты на калькуляторы тоже дадут разные числа, в зависимости с промежуточными результатами или нет.
-
Да не нужна мне абсолютная точность. Пусть считает как угодно. Вопрос-то в том, чтобы на разных мопьютерах получался один и тот же результат. Здесь http://www.delphikingdom.com/asp/viewitem.asp?catalogid=374 говорится о команде "Set8087CW(Get8087CW or $0100)" и др. Она может жестко установить точность вычислений для конкретной программы? Как она используется? Можно ли ее прописать в процедуре Create главной формы и свято верить что она установит правила вычислений для данной программы?
-
> Можно ли ее прописать в процедуре Create главной формы и > свято верить что она установит правила вычислений для данной > программы?
Нет. Любой вызов внешней функции теоретически может изменить управляющее слово процессора. Лучше делать такой вызов непосредственно перед каждым блоком вычислений.
Кстати, в современных версиях Delphi в модуле Math появилась более удобная функция для этих целей - SetPrecisionMode.
Кроме того, эта команда влияет только на режим точности, но не влияет на режим округления. Для его установки в Math есть ещё одна функция - SetRoundMode, она тоже вам может пригодиться.
|