Помощь - Поиск - Пользователи - Календарь
Полная версия: Калькулятор
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Делфи
antonioSP
Помогите плз с програмкой. Нужно сделать калькулятор считающий в разных системах счисления. В десятично я сделал, а как реализовать в других понятия не имею. Подскажите как лучше и проще это сделать.
volvo
В чем именно у тебя затруднения? Как это оформить, или как производить операции в других системах счисления (имеются в виду именно алгоритмы)?
antonioSP
Мне как раз не ясно как реализовать, какими алгоритмами и как лучше. Или же работать в заданной системе, или переводить в десятичную, а потом в заданную. Но как это реализовать не знаю.
volvo
Погоди... Насколько я помню, на форуме уже поднимался этот вопрос. В любом случае тебе придется переводить данные в какую-то одну систему счисления (о том, как это сделать - здесь: FAQ: Системы Счисления), и работать только в ней...
Lapp
Цитата(antonioSP @ 4.05.2006 18:45) *

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

Работать (производить действия над числами) можно просто в машинном представлении (тебя не должно волновать, какое оно), а ввод/вывод делать в нужной системе. Но это можно сделать только если тебе хватает разрядности машинного представления. Какая разрядность тебе нужна?
antonioSP
А можно ли работать в в одной и той же системе счисления, не переходя в десятичную?
Lapp
Цитата(antonioSP @ 5.05.2006 19:16) *

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

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

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

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

3. Можно плюнуть на всю машинную арифметику и реалиовать ее самому на чисто символьной основе ( то есть в пределах операций над цифрами той системы, с которой ты хочешь работать. Это значит, что нужно запрограммировать сложение, вычитание и умножение в столбик, а также деление уголком. При этом ты можешь сделать так, чтобы не привязывать все это к определенному основанию, тогда действия можно будет выполнять в той системе считсления, в которой записаны числа. Только мне это не очень по душе - такая реализация вряд ли будет быстро работать.. А кроме того, я полагаю, в твоем калькуляторе все равно должна присутствовать функция перевода чисел из одной сиситемы в другую..
antonioSP
Прошу помощи в поиске ошибке в процедуре 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
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
А вообще, я бы сделал так:
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
Спасибо тебе большое, правда функция не совсем корректно работает. Например если ввести 10 или 10.1 выдаёт один и тотже результат, лан буду сам разбираться.
volvo
Да, правильно. Не добавил еще одно условие:
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
Спасибо за помощь, но опять косячок. При вводе дробного значения например в 16-иричной сс с одним знаком после запятой, результат всегда получается *.0625, с двумя знаками после запятой *.06640625 и т.д. причём символ может быть любой не обязательно цифра.
volvo
Цитата(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
Цитата
Ну само собой Умножить-то найденную степень на значение соотв. разряда забыли...

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

Делай так:
Const
GradToRad = Pi / 180;
...
X := Cos(60 * GradToRad);
...
antonioSP
smile.gif Не знал что в Делфях в радианах. Спасибо тебе volvo ещё раз good.gif
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.