Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2010.01.10;
Скачать: CL | DM;

Вниз

Лажа с округлениями???   Найти похожие ветки 

 
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 вся ветка

Текущий архив: 2010.01.10;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.014 c
2-1258446240
Pascal96
2009-11-17 11:24
2010.01.10
Задача номер 2.


11-1205371733
Jon
2008-03-13 04:28
2010.01.10
KOL LabeledEdit


15-1254334797
Kerk
2009-09-30 22:19
2010.01.10
MySQL разность дат в днях


15-1257523019
Nikols
2009-11-06 18:56
2010.01.10
Программа для удаленного управления.


2-1258279449
@!!ex
2009-11-15 13:04
2010.01.10
Простой способ узнать, замкнуты контакты или нет.