Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 15.05.2015, 14:56   #1
Motoka
Новичок
Джуниор
 
Регистрация: 23.12.2013
Сообщений: 2
Печаль Работа с точкой в польской записи

Доброго времени суток. Пытаюсь сделать калькулятор на основе обратной польской записи. Требуемые функции реализовал, но вот проблема с вещественными числами. Когда вводится число, например: 4.2+2, получается результат 6.. дробную часть отказывается считать.. Пробовал разные варианты для решения этой проблемы, но, увы, ничего не получается.. Кто может помочь, помогите, пожалуйста.
Процедуры нажатия кнопок убрал, оставил основной алгоритм.
Код:
 
  private
    { Private declarations }
  public
    { Public declarations }
  end;

const
  prs = '+-ns^*/v(';
  pri: array [1 .. 9] of byte = (1, 1, 2, 2, 2, 2, 2, 2, 0);

var
  Form1: TForm1;
  s1, s2: String;
  q: array [0 .. 500] of Real;
  w: array [0 .. 500] of Char;
  n, len, len2: Cardinal;
  t,m: Real;
  ch: Char;
  i:integer;

implementation

{$R *.dfm}
procedure Push(x: Real);
begin
  Inc(len);
  q[len] := x;
end;
 
function Pop: Real;
begin
  Pop := q[len];
  q[len] := 0;
  Dec(len);
end;
 
procedure PushC(x: Char);
begin
  Inc(len2);
  w[len2] := x;
end;
 
function Popc: Char;
begin
  Popc := w[len2];
  w[len2] := #0;
  Dec(len2);
end;
 
function Oper(s1, s2: Real; s3: Char): Real;
var
  x, y, z: Real;
begin
  z:=0;
  x := s1;
  y := s2;
  case s3 of
    'n': z := Sin(y);
    's': z := Cos(y);
    '+': z := x + y;
    '-': z := x - y;
    'v': z := Sqrt(y);
    '^': z := Power(x,y);
    '*': z := x * y;
    '/': if y<>0 then z := x / y
          else
          begin
            ShowMessage('На нуль делить нельзя!');
            z:=0;
          end;
  end;
  Oper := z;
end;
 
procedure PreChange(var s: String);
var
  i: Cardinal;
begin
  if s[1] = '-' then
    s := '0' + s;
  i := 1;
  while i <= n do
    if (s[i] = '(') and (s[i + 1] = '-') then
      insert('0', s, i + 1)
    else
      Inc(i);
end;
 
function Change(s: String): String;
var
  i: Cardinal;
  rezs: String;
  c: Boolean;
begin
  c := false;
  for i := 1 to n do
    begin
      if not(s[i] in ['+', '-', 'n', 's', 'v', '^', '*', '/', '(', ')']) then
        begin
          if c then
            rezs := rezs + ' ';
          rezs := rezs + s[i];
          c := false;
        end
      else
        begin
          c := true;
          if s[i] = '(' then
            PushC(s[i])
          else
            if s[i] = ')' then
              begin
                while w[len2] <> '(' do
                  begin
                    rezs := rezs + ' ' + Popc;
                  end;
                Popc;
              end
            else
              if s[i] in ['+', '-', 'n', 's', 'v', '^', '*', '/'] then
                begin
                  while pri[Pos(w[len2], prs)] >= pri[Pos(s[i], prs)] do
                    rezs := rezs + ' ' + Popc;
                  PushC(s[i]);
                end;
        end;
    end;
  while len2 <> 0 do
    rezs := rezs + ' ' + Popc;
  Change := rezs;
end;
 
function Count(s: String): Real;
var
  ss: String;
  x, s1, s2: Real;
  chh, s3: Char;
  p, i, j: Cardinal;
  tmp: Integer;
begin
  i := 0;
  repeat
    j := i + 1;
    repeat
      Inc(i)
    until s[i] = ' ';
    ss := copy(s, j, i - j);
    chh := ss[1];
    if not(chh in ['+', '-', 'n', 's', 'v', '^', '*', '/']) then
      begin
        Val(ss, p, tmp);
        Push(p);
      end
    else
      begin
        s2 := Pop;
        s1 := Pop;
        s3 := chh;
        Push(Oper(s1, s2, s3));
      end;
  until i >= n;
  x := Pop;
  Count := x;
end;
 
procedure WriteL(x: Real);
var
  y, a, b: Cardinal;
  q: Real;
begin
  y := Trunc(x);
  b := 0;
  if Abs(x - y) < (1E-12) then
    Writeln(y)
  else
    begin
      if y > 0 then
        a := round(ln(y) / ln(10)) + 1
      else
        a := 1;
      q := x;
      repeat
        q := q * 10;
        Inc(b);
      until Abs(q - Trunc(q)) < (1E-12);
      Writeln(x:a + b:b);
    end;
end;

//процедура решения выражения(кнопка = или Calculate)
procedure TForm1.btn15Click(Sender: TObject);
begin
    edt2.Clear;
    s1:=edt1.Text;
    n := Length(s1);
    if (n = 0) then
    begin
      ShowMessage('Введите число!');
      Exit;
    end;
    for i:=1 to Length(s1) do
    if (s1[i] in [#48..#57,#40..#43,#45,#47,#32,#118,#99,#115,#94,#105,#110,#111,#46,'*']) then
    begin
      PreChange(s1);
      n := Length(s1);
      s2 := Change(s1);
      if s2[1] = ' ' then
        delete(s2, 1, 1);
      s2 := s2 + ' ';
      n := Length(s2);
      t := Count(s2);

    end
    else
    begin
          MessageDlg('Некорректный ввод',mtError, mbOKCancel, 0);
          Exit;
    end;
    edt2.text:=edt2.Text+floattostr(t);
end;
end.
Вложения
Тип файла: rar Calculate.rar (173.2 Кб, 9 просмотров)
Motoka вне форума Ответить с цитированием
Старый 15.05.2015, 15:31   #2
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

Цитата:
Код:
var
  p:Cardinal; 

// ss:='4.2';

        Val(ss, p, tmp);
Мы "хотим получить" даже не целое (integer) а натуральное (точнее беззнаковое) (cardinal)
Цитата:
Код:
Type	Range	Format
Integer	-2147483648..2147483647	signed 32-bit
Cardinal	0..4294967295	unsigned 32-bit
Вот и получаем 4.
Укажи правильный тип.
Цитата:
Val(Edit1.Text, I, Code);
{ Error during conversion to integer? }
if Code <> 0 then
MessageDlg('Error at position: ' + IntToStr(Code), mtWarning, [mbOk], 0, mbOk);
else
Canvas.TextOut(10, 10, 'Value = ' + IntToStr(I));
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 15.05.2015 в 15:37.
evg_m вне форума Ответить с цитированием
Старый 17.05.2015, 17:38   #3
Motoka
Новичок
Джуниор
 
Регистрация: 23.12.2013
Сообщений: 2
Радость

Спасибо большое за помощь, теперь все работает))
а то я бы так и мучил этот алгоритм)
Motoka вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Дополнить калькулятор на Обратной польской записи mith Помощь студентам 1 22.04.2015 09:49
Сделать подсчёт обратной польской записи Вечеслав Qt и кроссплатформенное программирование С/С++ 0 29.06.2013 17:27
Вопросы по обратной польской записи АлексВ Паскаль, Turbo Pascal, PascalABC.NET 8 01.06.2012 11:29
восстановление выражения по его прямой польской записи Котик Общие вопросы C/C++ 1 29.04.2010 22:30
преобразования польской формы записи уравнения Безбашик Общие вопросы по Java, Java SE, Kotlin 6 12.05.2009 10:25