Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 14.08.2011, 13:12
Аватар для SpectraL
SpectraL SpectraL вне форума
Начинающий
 
Регистрация: 19.05.2011
Адрес: Санкт-Петербург
Сообщения: 112
Версия Delphi: 10.1 Berlin
Репутация: 10
По умолчанию Неверный результат операции с участием вещественных чисел

Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  a,b,c: double;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  a := 212.53;
  b := 212.49;
  c := a - b;
  showmessage(floattostr(c));
end;

end.
Результатом "a-b" является 0.039999999999992. Что можно сделать чтобы переменной "c" присваивалось правильное значение (0.04)?

Последний раз редактировалось Admin, 15.08.2011 в 10:41.
Ответить с цитированием
  #2  
Старый 14.08.2011, 13:18
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

Код:
a,b,c: Currency;
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
  #3  
Старый 14.08.2011, 13:23
Аватар для SpectraL
SpectraL SpectraL вне форума
Начинающий
 
Регистрация: 19.05.2011
Адрес: Санкт-Петербург
Сообщения: 112
Версия Delphi: 10.1 Berlin
Репутация: 10
По умолчанию

Спасибо конешно за вариант, но а если "а" будет равно 212.4556565, а "b" будет равно 212.343676676?
Ответить с цитированием
  #4  
Старый 14.08.2011, 13:27
Аватар для SpectraL
SpectraL SpectraL вне форума
Начинающий
 
Регистрация: 19.05.2011
Адрес: Санкт-Петербург
Сообщения: 112
Версия Delphi: 10.1 Berlin
Репутация: 10
По умолчанию

Т.о. результатом "a-b" будет 0.111979824000002, а нужно 0.111979824.
Ответить с цитированием
  #5  
Старый 14.08.2011, 13:43
Аватар для NIch
NIch NIch вне форума
Продвинутый
 
Регистрация: 02.06.2008
Адрес: Бендеры ПМР
Сообщения: 754
Репутация: 2446
По умолчанию

Непонятно, то ты округляешь до 0,04 (3-го знака), то до 0.111979824 (9-го знака). Тогда уж или 0.039999999 или 0.112.
Напиши свою функцию округления и не парься.
__________________
В начале был Бит, потом Байт и только потом появилось Слово...
Ответить с цитированием
  #6  
Старый 14.08.2011, 13:52
Аватар для SpectraL
SpectraL SpectraL вне форума
Начинающий
 
Регистрация: 19.05.2011
Адрес: Санкт-Петербург
Сообщения: 112
Версия Delphi: 10.1 Berlin
Репутация: 10
По умолчанию

подразумевается что под "a" и "b" могут быть любые числа, а результат операции должен быть правильным... Для этого я должен написать свою функцию, а Delphi этого не предоставляет?
Ответить с цитированием
  #7  
Старый 14.08.2011, 13:58
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Это не Дельфи предоставляет, это суть вещественных чисел как их представляет процессор. Попробуй взять 1/3, что получится - бесконечная дробь, точного результата никогда не получишь, только приближённый.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
  #8  
Старый 14.08.2011, 14:00
Аватар для NIch
NIch NIch вне форума
Продвинутый
 
Регистрация: 02.06.2008
Адрес: Бендеры ПМР
Сообщения: 754
Репутация: 2446
По умолчанию

Есть готовая функция
Код:
function RoundEx(chislo: double; Precision: Integer): string;
var
  ChisloInStr: string;
  ChisloInCurr: currency;
begin
  ChisloInCurr := chislo;
  Str(ChisloInCurr: 20: Precision, ChisloInStr);
  ChisloInStr[Pos('.', ChisloInStr)] := ',';
  RoundEx := Trim(ChisloInStr);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
  Edit1.Text := RoundEx(StrToFloat(Edit1.Text), 2);
end;
http://www.delphisources.ru/pages/faq/base/round_n.html
ну или тут
http://www.delphisources.ru/pages/fa...d_numbers.html
__________________
В начале был Бит, потом Байт и только потом появилось Слово...
Ответить с цитированием
  #9  
Старый 14.08.2011, 14:07
Аватар для SpectraL
SpectraL SpectraL вне форума
Начинающий
 
Регистрация: 19.05.2011
Адрес: Санкт-Петербург
Сообщения: 112
Версия Delphi: 10.1 Berlin
Репутация: 10
По умолчанию

да, я в курсе что вещественные числа проблемно хранить в памяти сегодняшних компьютеров и операции осуществляются с неверным результатом...
Как я понимаю в Delphi отсутствует функция округления до необходимой цифры дробной части числа?
Ответить с цитированием
  #10  
Старый 14.08.2011, 14:13
Аватар для NIch
NIch NIch вне форума
Продвинутый
 
Регистрация: 02.06.2008
Адрес: Бендеры ПМР
Сообщения: 754
Репутация: 2446
По умолчанию

Мне такая неизвестна
Если посмотреть библиотеки делфи, то они все состоят из подобных функций, написанных на том же паскале порой с использованием винапи или ассемблера.
Что стоит воткнуть свою...
__________________
В начале был Бит, потом Байт и только потом появилось Слово...
Ответить с цитированием
  #11  
Старый 14.08.2011, 14:25
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Чем RoundTo, SimpleRoundTo не устраивает?
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
Этот пользователь сказал Спасибо angvelem за это полезное сообщение:
SpectraL (19.02.2015)
  #12  
Старый 14.08.2011, 14:36
Аватар для SpectraL
SpectraL SpectraL вне форума
Начинающий
 
Регистрация: 19.05.2011
Адрес: Санкт-Петербург
Сообщения: 112
Версия Delphi: 10.1 Berlin
Репутация: 10
По умолчанию

Цитата:
Сообщение от angvelem
Чем RoundTo, SimpleRoundTo не устраивает?
Спасибо, не знал о существовании таковых...
Ответить с цитированием
  #13  
Старый 14.08.2011, 14:39
Аватар для SpectraL
SpectraL SpectraL вне форума
Начинающий
 
Регистрация: 19.05.2011
Адрес: Санкт-Петербург
Сообщения: 112
Версия Delphi: 10.1 Berlin
Репутация: 10
По умолчанию

Цитата:
Сообщение от NIch
Есть готовая функция
Спасибо, посмотрю...
Ответить с цитированием
  #14  
Старый 14.08.2011, 17:11
Аватар для SpectraL
SpectraL SpectraL вне форума
Начинающий
 
Регистрация: 19.05.2011
Адрес: Санкт-Петербург
Сообщения: 112
Версия Delphi: 10.1 Berlin
Репутация: 10
По умолчанию

Результатом операции "a-b" является тип extended. При преобразовании типа extended в тип double ("c := a - b;") получаются такие неверные результаты. Поэтому лучшим решением нахожу сделать переменные "a, b и c" типом extended:
Цитата:
a, b, c: extended;
Однако, несмотря на то что
Цитата:
showmessage(c);
выводит правильный результат (0.04), условие
Цитата:
if c = 0.04 then showmessage('yes');
не выполняется. В таком случае помогает использование
Цитата:
c := strtofloat(floattostr(a - b));
Почему при showmessage, выводящем 0.04, не выполняется условие "if с = 0.04"? Нет ли более эффективного способа "обновить" значение 0.04 (strtofloat(floattostr(a - b)))?

Последний раз редактировалось SpectraL, 14.08.2011 в 17:57.
Ответить с цитированием
  #15  
Старый 15.08.2011, 09:26
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

SpectraL, так еще прикольней:
Код:
var
  a, b, c: Extended;
begin
  a:=212.53;
  b:=212.49;
  c:=a-b;
  Edit1.Text:=FloatToStr(c);
  Edit2.Text:=FloatToStr(0.04-c);
  if Abs(c-0.04)<1E-9 then ShowMessage('c=0.04');
end;
Edit1 = 0,04, а вот Edit2 = 6,105413483809E-18
красная строчка тебе в помощь!
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 18:32.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025