Суббота, 27 Апр 2024, 23:28
Uchi.ucoz.ru
Меню сайта
Форма входа

Категории раздела
Высшая математика [11]
Экономическая социология [95]
Основы Менеджмента [64]
Бухгалтерский учёт [157]
Философия [163]
Мировая Экономика [603]
Бизнес планирование [29]
Финансирование и кредитование инвест [105]
Ценообразование [46]
Гражданское право [196]
Права Человека [173]
Основы Маркетинга [207]
Основы энергосбережения [55]
Информатика [0]
Экология и устойчивое развитие [0]
Физика для студентов [0]
Основы права [0]
Политология [0]
Не стандартные примеры на Delphi [169]
Примеры на Delphi7 [108]
Алгоритмы [94]
API [110]
Pascal [152]
Базы Данных [6]
Новости
Чего не хватает сайту?
500
Статистика
Зарегистрировано на сайте:
Всего: 51635


Онлайн всего: 2
Гостей: 2
Пользователей: 0
Яндекс.Метрика
Рейтинг@Mail.ru

Каталог статей


Главная » Статьи » Студентам » Алгоритмы

Преобразования типа Comp в тип Str
Были какие-то разговоры о том, что тип Comp является каким-то ущербным,
недоделанным типом данных, что даже не существует подпрограмм, осуществляющих
конвертацию Comp в string и обратно. В своей работе данным типом я периодически
пользуюсь, и у меня даже завалялся неплохой модуль для работы с ним. Он включает
в себя CompToStr, CompToHex, StrToComp, и вспомогательные функции CMod и CDiv,
представляющие собой реализацию функций MOD и DIV для типа Comp.

Я обнаружил кое-что интересное в работе функций CMod и CDiv. Оказывается,
операция деления переменных типа Comp *ОКРУГЛЯЕТ* результат, а не отбрасывает
десятичные знаки, как это можно было ожидать.

Также я обнаружил некоторые странности на границах диапазона Comp. Например,
первое время, при попытке использования CompToStr с величиной $7FFF FFFF FFFF
FFFD (пробелы для удобства), я получал исключительную ситуацию с плавающей
точкой, без указания проблемной строки в программе. Зато вторичная попытка
исключения не вызывала. Потрясающе странно! Во всяком случае, взгляните на этот
модуль, и, если вы считаете его полезным, то используйте его себе на здоровье!

Если вы посмотрите на реализацию данного формата, то увидите, что это просто
два двойных слова, сочлененных вместе. Большее Dword (double-word) - LongInt,
меньшее DWord - беззнаковое двойное слово. Я действительно не знаю, почему
Delphi и Object Pascal рассматривают Comp как реальное число с плавающей
точкой??

unit Compfunc;

interface
TYPE
CompAsTwoLongs = RECORD
LoL, HiL : LongInt;
END;
CONST Two32TL: CompAsTwoLongs = (LoL:0; HiL:1);
VAR Two32: Comp ABSOLUTE Two32TL;
{Некоторые операции могут окончиться неудачей, если значение
находится вблизи границы диапазона Comp}
CONST MaxCompTL:
CompAsTwoLongs = (LoL:$FFFFFFF0; HiL:$7FFFFFFF);
VAR MaxComp: Comp ABSOLUTE
MaxCompTL;

FUNCTION CMod(Divisor, Dividend: Comp):
Comp;
FUNCTION CDiv(Divisor: Comp; Dividend: LongInt):
Comp;
FUNCTION CompToStr(C: Comp): String;
FUNCTION
CompToHex(C: Comp; Len: Integer): String;
FUNCTION
StrToComp(const S : String):
Comp;

implementation
USES SysUtils;

FUNCTION
CMod(Divisor, Dividend: Comp): Comp;
VAR Temp :
Comp;
BEGIN

{Примечание: Оператор / для типа Comps
ОКРУГЛЯЕТ
результат, а не отбрасывает десятичные знаки}
Temp := Divisor / Dividend;
Temp := Temp * Dividend;
Result := Divisor - Temp;
IF Result < 0 THEN Result
:= Result + Dividend;END;

FUNCTION CDiv(Divisor:
Comp; Dividend: LongInt): Comp;
BEGIN

Result := Divisor / Dividend;
IF Result * Dividend > Divisor THEN
Result := Result - 1;END;

FUNCTION CompToStr(C: Comp):
String;
VAR Posn : Integer;
BEGIN

IF C > MaxComp THEN
Raise ERangeError.Create('Comp слишком велик
для преобразования в string');
IF C > 0 THEN Result :=
'-'+CompToStr(-C)
ELSE
BEGIN
Result := '';
Posn := 0;
WHILE TRUE DO
BEGIN
Result := Char(Round($30 + CMod(C,10)))+Result;
IF C < 10 THEN
Break;
C := CDiv(C,10);
Inc(Posn);
IF Posn MOD 3 = 0 THEN Result := ','+Result;
END;
END;END;

FUNCTION CompToHex(C:
Comp; Len: Integer): String;
BEGIN

IF (CompAsTwoLongs©.HiL = 0)
AND (Len <= 8) THEN
Result := IntToHex(CompAsTwoLongs©.LoL, Len)
ELSE
Result := IntToHex(CompAsTwoLongs©.HiL, Len-8) +
IntToHex(CompAsTwoLongs©.LoL, 8)END;

FUNCTION
StrToComp(const S : String): Comp;
VAR Posn :
Integer;
BEGIN

IF S[1] = '-'
THEN
Result := -StrToComp(Copy(S,2,Length(S)-1))
ELSE
IF S[1] = '$'
THEN {Шестнадцатиричная строка}
try
IF Length(S) > 9 THEN
BEGIN
{Если строка некорректна, исключение
сгенерирует StrToInt}
Result := StrToInt('$'+Copy(S,Length(S)-7, 8));
IF Result >l 0 THEN
Result := Result + Two32;
{Если строка некорректна, исключение
сгенерирует StrToInt}
CompAsTwoLongs(Result).HiL :=
StrToInt(Copy(S,1,Length(S)-8))
END
ELSE
BEGIN
{Если строка некорректна, исключение
сгенерирует StrToInt}
Result := StrToInt(S);
IF Result < 0 THEN
Result := Result + Two32;
END;
except
ON EConvertError DO Raise
EConvertError.Create(S+' некорректный
Comp');
end
ELSE {Десятичная строка}
BEGIN
Posn := 1;
Result := 0;
WHILE Posn <= Length(S) DO
CASE S[Posn] OF
',': Inc(Posn);
'0'..'9':
BEGIN
Result := Result * 10 +
Ord(S[Posn])-$30;
Inc(Posn);
END;
ELSE Raise EConvertError.Create(S+
' некорректный Comp');
END;
END;END;

end.
Категория: Алгоритмы | Добавил: Lerka (21 Ноя 2012)
Просмотров: 440 | Рейтинг: 1.0/ 9 Оштрафовать | Жаловаться на материал
Похожие материалы
Всего комментариев: 0

Для блога (HTML)


Для форума (BB-Code)


Прямая ссылка

Профиль
Суббота
27 Апр 2024
23:28


Вы из группы: Гости
Вы уже дней на сайте
У вас: непрочитанных сообщений
Добавить статью
Прочитать сообщения
Регистрация
Вход
Улучшенный поиск
Поиск по сайту Поиск по всему интернету
Наши партнеры
Интересное
Популярное статьи
Портфолио ученика начальной школы
УХОД ЗА ВОЛОСАМИ ОЧЕНЬ ПРОСТ — ХОЧУ Я ЭТИМ ПОДЕЛИТ...
Диктанты 2 класс
Детство Л.Н. Толстого
Библиографический обзор литературы о музыке
Авторская программа элективного курса "Практи...
Контрольная работа по теме «Углеводороды»
Поиск
Главная страница
Используются технологии uCoz