|
Основной форум Сюда все проблемы связанные с программированием. |
31.03.2011, 20:45
|
#1
|
ПроЭктировщик
Регистрация: 31.01.2010
Адрес: Россия, респ. Башкортостан, г. Бирск
Сообщений: 137
Написано 12 полезных сообщений (для 17 пользователей)
|
Сложение вещественных чисел произвольной длины.
В общем мне оказалось нужно сделать это. Вещественные числа такого типа: [-]целое[.дробь]
Решил засунуть всё это в строку и для сложение только что написал следующую функцию. Но она слишком монструозная. Помойму я намудрил много. В общем вот:
function Addition(FirstSummand, SecondSummand : string; AdditionType : char;): string; var FSChar,SSChar : char; //положение чисел на корд. прямой относительно нуля. bufer : string; minus : boolean; //менять ли знак после действия. FSl,SSl,len,frlen : integer; //длина 1 и 2 числа, длина целой части большего, и длина большей дробной части. q,w,i : integer; ch1,ch2 : char; int,int1,int2 : integer; resultat : string; u : integer; begin //определение положения чисел на корд. прямой относительно нуля. FSChar:=getChar(FirstSummand,0); SSChar:=getChar(SecondSummand,0); if FSChar<>'-' then FSChar:='+'; if SSChar<>'-' then SSChar:='+'; //-------------------------------------------------------------------------------- //упрощение выражений. Например "a--b"="a+b" if (FSChar='-') and (Additiontype='-') and (SSChar='-') then begin SSChar:='+'; AdditionType:='+'; end; if (FSChar='-') and (AdditionType='+') and (SSChar='+') then begin bufer:=FirstSummand; FirstSummand:=SecondSummand; SecondSummand:=bufer; FSChar:='+'; SSChar:='+'; AdditionType:='-'; end; if SSChar='-' then if AdditionType='-' then AdditionType:='+'; else AdditionType:='-'; if (FSChar='-') and (AdditionType='-') then begin minus:=true; FSChar:='+'; AdditionType:='+'; end; if (FirstSummand<SecondSummand) and (AdditionType='-') then // если уменьшаемое меньше вычитаемого, удобнее будет их поменять местами. begin bufer:=FirstSummand; FirstSummand:=SecondSummand; SecondSummand:=bufer; if minus then minus:=false; else minus:=true; end; //------------------------------------------------------- //определение наибольших длин целой и дробной части u:=0; q:=length(FirstSummand); w:=length(SecondSummand); if pos(FirstSummand,'.')<>-1 then q:=pos(FirstSummand,'.'); if pos(SecondSummand,'.')<>-1 then w:=pos(SecondSummand,'.'); FSl:=length(copy(FirstSummand,0,q)); SSl:=length(copy(SecondSummand,0,w)); if FSl>=SSl then len:=FSl; else len:=SSl; if (length(FirstSummand)-q)>=(length(SecondSummand)-w) then frlen:=length(FirstSummand)-q; else frlen:=length(SecondSummand)-w; //---------------------------------------------------------------------------- //добавление нулей, для упрощения действия, а также для выравнивания положения запятой. FirstSummand:=StringWithZero(FirstSummand,len,frlen); SecondSummand:=StringWithZero(SecondSummand,len,frlen); //---------------------------------------------------------------------------- //само действие for i:=length(FirstSummand)-1 downto 0 do begin ch1:=getChar(FirstSummand,i); //считывание посимвольно с конца. ch2:=getChar(SecondSummand,i); if ch1<>'.' then begin int1:=StringToInteger(''+ch1); int2:=StringToInteger(''+ch2); if AdditionType='+' then // сложение begin int:=int1+int2; if int<10 then begin int:=int+u; //если в предыдущий раз сумма была больше 10 к int надо прибавить u resultat:=''+int+resultat; u:=0; //u использовали, опять делаем её нулевой end; else // если сумма цифр больше 10, то к следующему разряду нужно прибавить 1, это записываеться в u (на другое имя фагтазии не хватило :) ) begin int:=int-10+u; //вычитаем 10 и прибавляем последствия прошедших действий resultat:=''+int+resultat; u:=1; //ну и, конечно, инициируем u для следующего раза. end; end; else if AdditionType='-' then // вычитание begin if (int1-u)<int2 then // если первая цифра(с заранее учтёнными прошлыми действиями) меньше второй, то из следующей цифры уменьшаемого вычесть 1 begin int:=int1-u+10-int2; // из i-ной цифры уменьшаемого вычитаем i-ную цифру вычитаемого прибавляем 10, чтоб значение не было отрицательным и вычитаем u u:=1; // u естественно приравниваем 1 для следующего действия end; else // ничего нового, что надо было бы объяснять begin int:=int1-u-int2; u:=0; end; resultat:=''+int+resultat; end; end; else resultat:='.'+resultat; // дошли до точки, ставим точку и в результате end; if (u<>0) and (AdditionType='+') then // оставшиеся действия resultat:='1'+resultat; if (u<>0) and (AdditionType='-') then if minus then minus:=false; else minus:=true; if minus then Addition:='-'+resultat; else Addition:=resultat; //---------------------------------------- end;
Функция для добавлению нулей в начало и конец строки:
function StringWithZero(bufstring : string; int,frc : integer): string; var i : integer; bufstring2 : string; begin i:=1; if frc<>0 then begin if pos(bufstring,'.')=-1 then bufstring:=bufstring+'.'; bufstring2:=copy(bufstring,pos(bufstring,'.')+1,length(bufstring)); i:=0; while i<(frc-length(bufstring2)) do begin bufstring:=bufstring+'0'; i:=i+1; end; bufstring2:=copy(bufstring,0,pos(bufstring,'.')); i:=0; while i<(int-length(bufstring2)) do begin bufstring:='0'+bufstring; i:=i+1; end; end; else while i<(int-length(bufstring)+1) do begin bufstring:='0'+bufstring; i:=i+1; end; StringWithZero:=bufstring; end;
Последний раз редактировалось Ksanatos, 02.04.2011 в 05:29.
Причина: Устранил ошибки, теперь функции полностью рабочии.
|
(Offline)
|
|
01.04.2011, 22:24
|
#2
|
Мастер
Регистрация: 03.05.2010
Адрес: Подмосковье
Сообщений: 1,218
Написано 438 полезных сообщений (для 790 пользователей)
|
Ответ: Сложение вещественных чисел произвольной длины.
Код вроде как хороший, тока разобраться без комментов трудновато (между '//само действие' и '//---------')
UPD: вроде разобрался.
__________________
О¯О ¡¡¡ʁɔvʎнdǝʚǝdǝu dиW
|
(Offline)
|
|
02.04.2011, 03:00
|
#3
|
ПроЭктировщик
Регистрация: 31.01.2010
Адрес: Россия, респ. Башкортостан, г. Бирск
Сообщений: 137
Написано 12 полезных сообщений (для 17 пользователей)
|
Ответ: Сложение вещественных чисел произвольной длины.
Простите за отсутствие комментов. Вчера я был уже пуст и заново понять то что написал не получалось ))
Хотелось бы услышаь предложения по сжатию этого кода, если это вообще возможно...
Последний раз редактировалось Ksanatos, 02.04.2011 в 05:31.
|
(Offline)
|
|
02.04.2011, 22:47
|
#4
|
ПроЭктировщик
Регистрация: 19.02.2011
Сообщений: 134
Написано 81 полезных сообщений (для 219 пользователей)
|
Ответ: Сложение вещественных чисел произвольной длины.
Пожалуй, при использовании "чистого" МП максимальной скорости выполнения достигнуть не возможно, просто потому что код не транслируется нужным способом, и не работает на максимальной скорости.
Если вам функция до сих пор нужна, я написал аналогичную (точнее, несколько их) на "чистой" яве и сделал библиотеку -
http://forum.boolean.name/showthread...ewpost&t=14515
По ЛС могу сбросить исходный код - функции занимают 26, 34, и 42 строк для сложения, вычитания, и умножения соответственно.
__________________
Мой сайт-блог. Игры, обновления, примеры для Haxe, JavaScript(+HTML5), GameMaker, Love2d...
|
(Offline)
|
|
02.04.2011, 22:58
|
#5
|
Дэвелопер
Регистрация: 13.02.2010
Сообщений: 1,645
Написано 620 полезных сообщений (для 2,419 пользователей)
|
Ответ: Сложение вещественных чисел произвольной длины.
А в телефонной Java нет классов BigInteger и BigDecimal ??
|
(Offline)
|
|
02.04.2011, 23:47
|
#6
|
ПроЭктировщик
Регистрация: 19.02.2011
Сообщений: 134
Написано 81 полезных сообщений (для 219 пользователей)
|
Ответ: Сложение вещественных чисел произвольной длины.
Сообщение от Den
А в телефонной Java нет классов BigInteger и BigDecimal ??
|
В спецификацию не включен ни то что java.lang.Number, а даже java.math, из которого берутся все функции. То есть как факт, вы можете тестировать MIDlet с таким типом на компьютере (через эмулятор), но на устройстве он будет падать на запуске с "No class definition found".
__________________
Мой сайт-блог. Игры, обновления, примеры для Haxe, JavaScript(+HTML5), GameMaker, Love2d...
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
03.04.2011, 16:13
|
#7
|
Мастер
Регистрация: 03.05.2010
Адрес: Подмосковье
Сообщений: 1,218
Написано 438 полезных сообщений (для 790 пользователей)
|
Ответ: Сложение вещественных чисел произвольной длины.
Маленький совет по оптимизации. Можно в каждый символ писать не одну цифру, а две. (ord и chr в помощь)
Количество операций должно уменьшится почти в два раза.
__________________
О¯О ¡¡¡ʁɔvʎнdǝʚǝdǝu dиW
|
(Offline)
|
|
04.04.2011, 14:59
|
#8
|
Знающий
Регистрация: 16.09.2008
Сообщений: 299
Написано 71 полезных сообщений (для 123 пользователей)
|
Ответ: Сложение вещественных чисел произвольной длины.
вот пример, но только для сложения положительных чисел:
var
idTxt : integer;
cmdExit : command;
a,b : string;
function sum(a,b : string) : string;
var
s : string;
ap,bp : integer;
sm,ost : integer;
begin
ap:=pos(a,'.');
bp:=pos(b,'.');
if (ap=-1) then begin a:=a+'.'; ap:=pos(a,'.'); end;
if (bp=-1) then begin b:=b+'.'; bp:=pos(b,'.'); end;
while (ap<bp) do begin a:='0'+a; ap:=ap+1; end;
while (bp<ap) do begin b:='0'+b; bp:=bp+1; end;
ap:=length(a);
bp:=length(b);
while (ap<bp) do begin a:=a+'0'; ap:=ap+1; end;
while (bp<ap) do begin b:=b+'0'; bp:=bp+1; end;
s:='';
ost:=0;
for ap:=bp-1 downto 0 do
begin
if getChar(a,ap)<>'.' then
begin
sm:=(ord(getChar(a,ap))-48) + (ord(getChar(b,ap))-48);
if ost>0 then begin sm:=sm+ost; ost:=0; end;
while sm>=10 do begin sm:=sm-10; ost:=ost+1; end;
s:=''+sm+s;
end
else s:='.'+s;
end;
if ost>0 then s:=''+ost+s;
sum:=s;
end;
begin
showForm;
a:='12999999';
b:='6789.2999';
idTxt := formAddString(a+'+'+b+'='+sum(a,b));
cmdExit := createCommand('Exit', CM_EXIT, 1);
addCommand(cmdExit);
repeat delay(1000); until getClickedCommand=cmdExit;
end.
|
(Offline)
|
|
04.04.2011, 22:29
|
#9
|
ПроЭктировщик
Регистрация: 31.01.2010
Адрес: Россия, респ. Башкортостан, г. Бирск
Сообщений: 137
Написано 12 полезных сообщений (для 17 пользователей)
|
Ответ: Сложение вещественных чисел произвольной длины.
Спасибо всем.
2YellowAfterlife
Я уже написал две функции(сложение и вычитание вместе и умножение) универсальные, для всех типов чисел сразу, на МП. Внедрять в проект твою либу, пока слишком муторно выйдет. Но всё равно спасибо. Сейчас ломаю голову над делением...
По ЛС могу сбросить исходный код
|
В яве не силён, пока только учусь, так что, врятли я что-нибудь пойму...
И вопрос тебе:
в одном объекте String может хранится до двух миллиардов символов
|
в МП также или только 255 символов?
2Igor
Не катит, я повсеместно использую pos...
2abcdef
Спасибо, у себя много недочётов нашел.
while sm>=10 do begin sm:=sm-10; ost:=ost+1; end;
|
строчка лишняя, больше 18 нельзя получить при сумме двух цифр и ещё единица с предыдущего сложения.
|
(Offline)
|
|
05.04.2011, 02:46
|
#10
|
ПроЭктировщик
Регистрация: 19.02.2011
Сообщений: 134
Написано 81 полезных сообщений (для 219 пользователей)
|
Ответ: Сложение вещественных чисел произвольной длины.
Сообщение от Ksanatos
Спасибо всем.
2YellowAfterlife
Я уже написал две функции(сложение и вычитание вместе и умножение) универсальные, для всех типов чисел сразу, на МП. Внедрять в проект твою либу, пока слишком муторно выйдет. Но всё равно спасибо. Сейчас ломаю голову над делением...
В яве не силён, пока только учусь, так что, врятли я что-нибудь пойму...
И вопрос тебе:
в МП также или только 255 символов?
|
МП так же поддерживает длинные строки, потому что, о чудо, Никса не реализовал их через int'ы, в отличие от всех остальных типов переменных (да, даже boolean хранится в МП-МИДлете как int). Максимальное число символов - 2147483647 (0x7FFFFFFF). Хотя, в прочем, не очень вероятно что это имеет значение, учитывая то что на телефонах нет столько памяти
Про библиотеку - я ее сделал, поскольку "обычные" методы java работают в разы быстрее даже самых правильных функций в МП (см. те же непонятные преобразования ((booleancondition ? 1 : 0) != 0) почти на каждом if'е, сделанным МП).
Функция realaddreal из библиотеки работает где-то так же как и ваша (принимает значения независимо от точки и знака, и делает все возможное для избежания ошибок). Остальные функции добавлены, поскольку при известном типе числа они обеспечивают даже большую производительность программы.
__________________
Мой сайт-блог. Игры, обновления, примеры для Haxe, JavaScript(+HTML5), GameMaker, Love2d...
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
24.06.2011, 02:54
|
#11
|
ПроЭктировщик
Регистрация: 31.01.2010
Адрес: Россия, респ. Башкортостан, г. Бирск
Сообщений: 137
Написано 12 полезных сообщений (для 17 пользователей)
|
Ответ: Сложение вещественных чисел произвольной длины.
Проект куда я всё это запихнул ^_^.
|
(Offline)
|
|
Ваши права в разделе
|
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 04:10.
|