Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Делфи _ Калькулятор

Автор: antonioSP 4.05.2006 17:17

Помогите плз с програмкой. Нужно сделать калькулятор считающий в разных системах счисления. В десятично я сделал, а как реализовать в других понятия не имею. Подскажите как лучше и проще это сделать.

Автор: volvo 4.05.2006 18:10

В чем именно у тебя затруднения? Как это оформить, или как производить операции в других системах счисления (имеются в виду именно алгоритмы)?

Автор: antonioSP 4.05.2006 22:45

Мне как раз не ясно как реализовать, какими алгоритмами и как лучше. Или же работать в заданной системе, или переводить в десятичную, а потом в заданную. Но как это реализовать не знаю.

Автор: volvo 4.05.2006 22:52

Погоди... Насколько я помню, на форуме уже поднимался этот вопрос. В любом случае тебе придется переводить данные в какую-то одну систему счисления (о том, как это сделать - здесь: http://forum.pascal.net.ru/index.php?s=&showtopic=4535&view=findpost&p=38226), и работать только в ней...

Автор: lapp 5.05.2006 5:48

Цитата(antonioSP @ 4.05.2006 18:45) *

Или же работать в заданной системе, или переводить в десятичную, а потом в заданную.

Работать (производить действия над числами) можно просто в машинном представлении (тебя не должно волновать, какое оно), а ввод/вывод делать в нужной системе. Но это можно сделать только если тебе хватает разрядности машинного представления. Какая разрядность тебе нужна?

Автор: antonioSP 5.05.2006 23:16

А можно ли работать в в одной и той же системе счисления, не переходя в десятичную?

Автор: lapp 6.05.2006 11:32

Цитата(antonioSP @ 5.05.2006 19:16) *

А можно ли работать в в одной и той же системе счисления, не переходя в десятичную?

Уважаемый antonioSP, почему ты не отвечаешь на вопросы - думаешь, только тебе должны отвечать? Пойми, это же не из праздного любопытства! Мы честно стараемся тебе помочь. И без условий на разрядность (то есть сколько цифр - скажем, в 16-ричной записи числа) тебе нужно, помочь тебе трудно. Смотри.

1. Если числа не очень большие (в пределах того, что может обеспечить LongInt, скажем), то заботиться об операциях вообще не нужно. Нужно просто ввести число, то есть расшифровать ту запись, которая есть (двоичная, десятичная или еще какая), а потом работать с просто числом, как обычно. А когда ты произведешь все действия, ты результат выведешь в нужной системе. Это понятно?

2. Если числа большие, то можно реализовать "Очень длинную арифметику", составляя числа из нескольких LongInt (это было на Форуме, поищи). Если это сделано, то в остальном принцип работы тот же, что и в п.1.

3. Можно плюнуть на всю машинную арифметику и реалиовать ее самому на чисто символьной основе ( то есть в пределах операций над цифрами той системы, с которой ты хочешь работать. Это значит, что нужно запрограммировать сложение, вычитание и умножение в столбик, а также деление уголком. При этом ты можешь сделать так, чтобы не привязывать все это к определенному основанию, тогда действия можно будет выполнять в той системе считсления, в которой записаны числа. Только мне это не очень по душе - такая реализация вряд ли будет быстро работать.. А кроме того, я полагаю, в твоем калькуляторе все равно должна присутствовать функция перевода чисел из одной сиситемы в другую..

Автор: antonioSP 19.05.2006 16:38

Прошу помощи в поиске ошибке в процедуре ToDec для калькулятора, чтобы переводила дробные значения какой-то сс в десятичную. Она ещё не доработана (не работает для чисел в сс>10),но хотелось бы попробывать сначало хотябы с дробными двоичными.

function stepen(a,n:integer):integer;
var
s,i:integer;
begin
for i:=1 to n do
s:=s*a;
stepen:=s;
end;

function ToDec(n:string; radix:longint):real;
var
l,d:real;
m,i:longint;
const
digit: string[16]='0123456789ABCDEF';
begin
l:= strtofloat(n);
if frac(l)>0 then
begin
m:=0;
while n[1]='0' do delete(n,1,1);
for i:=1 to length(n) do m:=m*radix+pos(n[i],digit)-1;
d:=0;
for i:=1 to length(floattostr(frac(l))) do
if i>1 then d:=d+1/stepen(radix,(i-1));// ошибка возникает тут
todec:=int(m)+d;
end
else
begin
m:=0;
while n[1]='0' do delete(n,1,1);
for i:=1 to length(n) do m:=m*radix+pos(n[i],digit)-1;
ToDec:=m;
end
end;

Просьба не смеятся на корявым (пока ещё) алгоритмом smile.gif

Автор: volvo 19.05.2006 16:47

antonioSP, ошибка далеко не там, где тебе кажется:

function stepen(a,n:integer):integer;
var s, i: integer;
begin
s := 1; // <--- Вот это добавь !!!
for i := 1 to n do s := s*a;
stepen:=s;
end;
и деление на ноль не будет возникать smile.gif

Автор: volvo 19.05.2006 17:15

А вообще, я бы сделал так:

function ToDec(n:string; radix:longint):real;
var
_int: longint;
_frac: real;

s: string;
i, p: byte;
const
digit: string[16]='0123456789ABCDEF';

begin
p := pos('.', n);
if p = 0 then s := n
else s := copy(n, 1, p - 1);

_int := 0; _frac := 0.0;

// В целой части удаляем ведущие нули
while s[1] = '0' do delete(s, 1, 1);
for i := 1 to length(s) do
_int := _int * radix + pos(n[i], digit) - 1;

if p < length(n) then begin

s := copy(n, p + 1, 255);
// В дробной части удалять можно НЕзначащие, завершающие нули
while s[length(s)] = '0' do delete(s, length(s), 1);

for i := 1 to length(s) do
_frac := _frac + 1 / stepen(radix, i);

end;
ToDec := _int + _frac;
end;

Автор: antonioSP 19.05.2006 19:47

Спасибо тебе большое, правда функция не совсем корректно работает. Например если ввести 10 или 10.1 выдаёт один и тотже результат, лан буду сам разбираться.

Автор: volvo 19.05.2006 20:03

Да, правильно. Не добавил еще одно условие:

function ToDec(n:string; radix:longint):real;
var
_int: longint;
_frac: real;

s: string;
i, p: byte;
const
digit: string[16]='0123456789ABCDEF';

begin
p := pos('.', n);
if p = 0 then s := n
else s := copy(n, 1, p - 1);

_int := 0; _frac := 0.0;

while s[1] = '0' do delete(s, 1, 1);
for i := 1 to length(s) do
_int := _int * radix + pos(n[i], digit) - 1;

if (p <> 0) and (p < length(n)) then begin // <--- Здесь !!!

s := copy(n, p + 1, 255);
while s[length(s)] = '0' do delete(s, length(s), 1);

for i := 1 to length(s) do
_frac := _frac + 1 / stepen(radix, i);

end;
ToDec := _int + _frac;
end;


Проверь сейчас.

Автор: antonioSP 19.05.2006 21:14

Спасибо за помощь, но опять косячок. При вводе дробного значения например в 16-иричной сс с одним знаком после запятой, результат всегда получается *.0625, с двумя знаками после запятой *.06640625 и т.д. причём символ может быть любой не обязательно цифра.

Автор: volvo 27.05.2006 23:47

Цитата(antonioSP @ 19.05.2006 17:14)
Спасибо за помощь, но опять косячок.
Ну само собой lol.gif Умножить-то найденную степень на значение соотв. разряда забыли...

function ToDec(n:string; radix:longint):real;
var
_int: longint;
_frac: real;

s: string;
i, p: byte;
const
digit: string[16]='0123456789ABCDEF';

begin
p := pos('.', n);
if p = 0 then s := n
else s := copy(n, 1, p - 1);

_int := 0; _frac := 0.0;

while s[1] = '0' do delete(s, 1, 1);
for i := 1 to length(s) do
_int := _int * radix + pos(n[i], digit) - 1;

if (p <> 0) and (p < length(n)) then begin

s := copy(n, p + 1, 255);
while s[length(s)] = '0' do delete(s, length(s), 1);

for i := 1 to length(s) do
_frac := _frac + pred(pos(upcase(s[i]), digit)) / stepen(radix, i); // <--- Тут ...

end;
ToDec := _int + _frac;
end;

Автор: antonioSP 28.05.2006 23:00

Цитата
Ну само собой Умножить-то найденную степень на значение соотв. разряда забыли...

Это я уже заметил и исправил smile.gif Но у меня опять проблема. unsure.gif У меня почемуто Делфи неправильно считает функции cos и sin, например если ввести cos(0) то получается правильно 1, а со всеми остальными неправильно: cos(1)=0,54, cos(60)=-0,95 и т.д. Конечно можно воспользоваться функциями разложения в ряд, но хотелось чтобы программа покороче была. Помогите пожалуйста.

Автор: volvo 28.05.2006 23:14

Аргумент передаешь в градусах? А Delphi вообще-то принимает в радианах smile.gif А Cos(60 радиан) как раз и равен -0.95

Делай так:

Const
GradToRad = Pi / 180;
...
X := Cos(60 * GradToRad);
...

Автор: antonioSP 28.05.2006 23:28

smile.gif Не знал что в Делфях в радианах. Спасибо тебе volvo ещё раз good.gif