Форум: "WinAPI";
Текущий архив: 2010.01.10;
Скачать: [xml.tar.bz2];
ВнизЛажа с округлениями??? Найти похожие ветки
← →
DimDim (2008-11-10 12:02) [0]Уважаемые Мастера! Первый раз с таким столкнулся и вполном замешательстве...
В таблице:
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
Это что?
← →
Anatoly Podgoretsky © (2008-11-10 12:10) [1]> DimDim (10.11.2008 12:02:00) [0]
Это может какая ни будь программа, которая меняет маску.
← →
DimDim (2008-11-10 12:41) [2]Причем здесь маска? Я программно округляю до 2-х знаков после запятой.
Программа, меняющая математику процессора?
Компьютер - это усовершенствованый калькулятор. Как можно поменять в принципе незыблимые в природе законы математики? Я понимаю, что для компьютера 2*2 = примерно 4. Но законы округления на едентичных машинах должны быть одинаковые...
← →
Сергей М. © (2008-11-10 12:48) [3]
> DimDim
Программа твоя ?
Тогда непосредственно перед вызовом Round вызови GetRoundMode и посмотри режим округления
← →
DimDim (2008-11-10 13:01) [4]Программа моя.
Закзчик (где эта х... проявилась) далековато.
С GetRoundMode ниразу не сталкивался. Что она дает? Можно поподробней?
Да и толку что я узнаю режим округлений? Бороться с этим как?
← →
Сергей М. © (2008-11-10 13:07) [5]
> Закзчик ..далековато.
Это твоя личная драма.
> Что она дает? Можно поподробней?
см. справку, там все написано.
> толку что я узнаю режим округлений?
Как минимум подтвержишь или опровергнешь факт того, что разные экз-ры твоей программы на разных машинах используют при округлении разные его режимы, из-за чего отличаются результаты округления
← →
DimDim (2008-11-10 13:09) [6]Да и мне, собственно, по барабану в какую сторону она 5 округляет - лижбы у всех одинаково округляла...
← →
Сергей М. © (2008-11-10 13:23) [7]
> лижбы у всех одинаково округляла
Тогда проверяй региональные установки у каждого пользователя.
← →
Anatoly Podgoretsky © (2008-11-10 14:35) [8]> DimDim (10.11.2008 13:01:04) [4]
www.intel.com архитектура процессора.
← →
Anatoly Podgoretsky © (2008-11-10 14:36) [9]> DimDim (10.11.2008 13:09:06) [6]
Тогда обеспечить у всех одинаковую среду
← →
DimDim (2008-11-10 22:26) [10]Ну, про региональные установки - это первое что пришло на мысль. Но там ведь нихр... похожего нет. Да и быть не может. Даже в африке 2*2=4. Если какая-то настройка и есть, то где-то на уровне биоса.
> Тогда обеспечить у всех одинаковую среду
Пользуется программой 400 заказчиков (около 1000 компов). ИЗДЕВАЕТЕСЬ???
Попробую переписать процедуры округлений в такой вид:
Round((PoleCena*PoleKol*100)+0.0000000000000001)/100
может поможет. Буду надеяться, что это не повлияет на другие вычисления.
Но все равно это не правильно! У меня в корне подорвана вера в вычислительную технику! Один и тот же расчет, сделаный на разных компах может дать разные результаты? Бред...
← →
Anatoly Podgoretsky © (2008-11-10 23:02) [11]> DimDim (10.11.2008 22:26:10) [10]
Бред, при одинаковых условиях - результаты одинаковые.
← →
DimDim (2008-11-11 01:28) [12]Какие нах... условия в элементарной математике!???
Или может от каких-то условий теорема Пифагора может поменяться?
Я сам свято верил что такого быть не может! Пока мне заказчики пальцем не показали.
← →
Сергей М. © (2008-11-11 08:51) [13]
> DimDim (11.11.08 01:28) [12]
И чего ты разнахался ?)
Не трожь элементарную математику - в ней еще и не такие чудеса происходят)
Вот тебе пища для размышления:
procedure TForm1.Button1Click(Sender: TObject);
type
// Float = Double; // <- сначала раскомментируй эту строчку
// Float = Single; // <- а теперь эту
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-тип поля дейтасета на каждом из рассматриваемых тобой компах)
← →
DimDim (2008-11-11 12:17) [14]Все это понятно. И наглядней это будет так:
procedure TForm1.Button1Click(Sender: TObject);
type
//Float = Double; // <- сначала раскомментируй эту строчку
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 из-за каких-то настроек?
Ну, я бы мог это понять, если бы один и тот расчет выполнялся в разных вариантах программы с разными типами переменных.
В принципе, очень поучительный пример с точки зрения общей теории. А делать-то чаво? Узнал от заказчика много интересного о себе... Их теория не интересует - их интересует достоверность расчета.
← →
Сергей М. © (2008-11-11 12:40) [15]Я хочу сказать только одно : видимый результат (с маской или без маски - индифферентно) так или иначе зависит от формата хранения и представления чисел с п/з - как операндов, так и результата.
Вероятно, следует сосредоточиться на исследовании среды функционирования СУБД, с которой работает твоя программа - именно она поставляет для TFloatField-операндов данные в формате чисел с п/з . Один клиент получает их в виде Single-типа и видит в результате дальнейших вычислений один результат, а другой клиент получает, скажем, Double-тип и видит, как ты уже убедился, другой результат.
> Узнал от заказчика много интересного о себе
И он прав - ты как разработчик должен был предвидеть такую ситуацию .. или же принять меры к идентичности СУБД-среды
← →
Anatoly Podgoretsky © (2008-11-11 15:27) [16]> DimDim (11.11.2008 12:17:14) [14]
Не настроек, а масок процессора - контрольное слово процессора. Обычное дело, из-за твоего коды ты обязан был рано или позно попасть, поскольку код предполагает эту "ошибку". Нафиг делать такое кривое округление до двух, которое к тому же бессмысленно без маски вывода в f-FormatFloat поскольку float это число с плавающей запятой и системе глубоко пофиг на твои изращения. Почитай на Королевстве, что это такое.
← →
DimDim (2008-11-12 00:34) [17]Я отлично понимаю что такое число с плавающей точкой и почему одно и то же число в разных типах переменных не равны.
"Такое кривое округление" делается не от хорошей жизни, а потому что от результата делается еще мульен вычислений. Причем, в расчетах он печатается как промежуточный. Отображать через маску не округленный результат - тогда лажа (точнее - не понятные заказчику числа) вылазят в дальнейшем расчете.
Программа по расчету сметной стоимости строительства. Конечные расчеты (сметы, акты и т.д.) проверяются двумя сторонами - кто их составляет и для кого они составляются. Проверяют обычно от одного промежуточного результата до другого. ПРОВЕРЯЮТ КАЛЬКУЛЯТОРОМ! И при проверке смотрят на промежуточные результаты ИЗ РАСПЕЧАТКИ. Каждому не объяснишь что в распечатке предполагаются точные числа. А уж тем более что на одном компе посчитано с точностью Extended, а на другом, почему-то, с точность Single. Поэтому КАЖДЫЙ промежуточный результат (который выводится в распечатки) приходится явным образом округлять, чтобы избежать лишних вопросов. Я уже молчу, что в программе предусмотрена пользовательская система настройки точности вычислений...
Если бы результат округления был бы некий конечный результат, который распечатать и забыть - то проблемы бы небыло - однозначно FormatFloat.
← →
Anatoly Podgoretsky © (2008-11-12 00:46) [18]> DimDim (12.11.2008 0:34:17) [17]
Но в твоих примерах, не в расчете, а простой вывод на метку.
Если нужна абсолютная точность, то надо использовать точные, а не приблизительные числа, не Float, а BCD, в крайнем случае Currency.
Но ведь и в этом случае операции не коммутативны. A/B * B <> A, попробуй 1/2*3 c промежуточными результатами.
Расчеты на калькуляторы тоже дадут разные числа, в зависимости с промежуточными результатами или нет.
← →
DimDim (2008-11-12 11:22) [19]Да не нужна мне абсолютная точность. Пусть считает как угодно. Вопрос-то в том, чтобы на разных мопьютерах получался один и тот же результат.
Здесь http://www.delphikingdom.com/asp/viewitem.asp?catalogid=374 говорится о команде "Set8087CW(Get8087CW or $0100)" и др. Она может жестко установить точность вычислений для конкретной программы? Как она используется? Можно ли ее прописать в процедуре Create главной формы и свято верить что она установит правила вычислений для данной программы?
← →
Григорьев Антон © (2008-11-12 16:16) [20]
> Можно ли ее прописать в процедуре Create главной формы и
> свято верить что она установит правила вычислений для данной
> программы?
Нет. Любой вызов внешней функции теоретически может изменить управляющее слово процессора. Лучше делать такой вызов непосредственно перед каждым блоком вычислений.
Кстати, в современных версиях Delphi в модуле Math появилась более удобная функция для этих целей - SetPrecisionMode.
Кроме того, эта команда влияет только на режим точности, но не влияет на режим округления. Для его установки в Math есть ещё одна функция - SetRoundMode, она тоже вам может пригодиться.
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2010.01.10;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.013 c