Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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.008 c
15-1257712925
POOP
2009-11-08 23:42
2010.01.10
При отражении длина световой волны меняется?


1-1233066145
webpauk
2009-01-27 17:22
2010.01.10
курсор в Tedit


2-1258384893
Кузьма
2009-11-16 18:21
2010.01.10
Работа с отладчиком в Дельфи


15-1257489395
vajo
2009-11-06 09:36
2010.01.10
Как астрономы добиваются такой точности?


15-1256930126
Суслик_
2009-10-30 22:15
2010.01.10
Разработка приложения для в рамках в Win Terminal Service





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский