Прииспользованиифункции StrToFloat() длязначения 1234.5544 яполучаючто-тотипа 1234.55440000000003, новедьэтонеправильно! Ничегоздесьнеправильногонет. Этопростопогрешностьчиселсплавающейточкой. Фактическиисточникомошибкиявляетсяошибкаокругления. Даннаяошибкаявляетсяследствиемдефектаарифметикиплавающейточкиитогофакта, чточащевсегодесятичныедробиявляютсяповторяющимисядолямивдвоичнойсистемесчисления. Такиечисланемогутпредставлятьсявконечномколичествебитов. Всвязисэтимтекстовоеокруглениеполучаетсяневсегдаточным, т.к. большинствокомпьютеровподбираетпоследниецифрыдробнойчасти, исходяизближайшего (снаименьшейразницей) эквивалента. Некоторыекомпьютерынепроизводятокругления, апростообрезают (выключают) последниебиты, получаярезультирующуюошибку, правильноназываемуюошибкойокругления (впротивоположностьошибкеусечения, когдаусекаетсярасширениеряда). Дляполучениядополнительнойинформацииобратитеськ Introduction to Numerical Methods (введениевчисловыеметоды) авторов Peter A. Stark, Macmillian Company, 1970. Из-заналичияошибкисравнениедвухчиселсплавающейточкойсводитсякучетуабсолютнойилиотносительнойпогрешности. Длясравнениядвухчиселсучетомабсолютнойпогрешностииспользуйтеследующийкод:

Code:

IF ABS(CalculatedValue - TrueValue) < FuzzValue then ...

 

, где FuzzValue определяетвеличинуабсолютнойпогрешности. Длясравнениядвухчиселсучетомотносительнойпогрешностииспользуйтеследующийкод:

Code:

IF ABS( (CalculatedValue - TrueValue) / TrueValue ) <

AcceptableRelativeError then ...

 

, где AcceptableRelativeError определяетвеличинуотносительнойпогрешности (ну, иконечно, TrueValue <> 0.0). Математеческиймодуль Delphi вычисляетотносительнуюпогрешностьследующимобразом (ноононевынесеновсекцию interface):

Code:

FUNCTION RelSmall(X, Y: Extended): Boolean;

{ Возвращаем Истину, если разница между X и Y незначительна }

CONST

C1: Double = 1E-15;

C2: Double = 1E-12;

BEGIN

Result := Abs(X) < (C1 + C2 * Abs(Y))

END;

 

 

Code:

function BinToInt(const Value: string): Integer;

{©Drkb v.3(2007): www.drkb.ru}

var

i, strLen: Integer;

begin

Result := 0;

strLen := Length(Value);

for i := 1to strLen do

if Value[i] = '1'then

Result := Result or (1shl (strLen - i))

else

Result := Result andnot (1shl (strLen - i));

end;

 

 

Автор: Yanis

Прибавляешь 0.5 затем отбрасываешь дробную часть:

 

Code:

Uses Math;

{©Drkb v.3(2007): www.drkb, 

®Vit (Vitaly Nevzorov) - nevzorov yahoo. com}

 

Function RoundMax(Num:real; prec:integer):real;

begin

result:=roundto(num+Power(10, prec-1)*5, prec);

end;

 

До сотых соответственно будет:

 

Code:

Function RoundMax100(Num:real):real;

{©Drkb v.3(2007): www.drkb.ru,

®Vit (Vitaly Nevzorov) - Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.}

 

begin

result:=round(num*100+0.5)/100;

end;

 

Code:

function dec2hex(value: dword): string[8];

const

hexdigit = '0123456789ABCDEF';

begin

while value <> 0do

begin

dec2hex := hexdigit[succ(value and$F)];

value := value shr4;

end;

if dec2hex = ''then dec2hex := '0';

end;

Code:

unit Bitwise;

 

interface

 

function IsBitSet(const val: longint; const TheBit: byte): boolean;

function BitOn(const val: longint; const TheBit: byte): LongInt;

function BitOff(const val: longint; const TheBit: byte): LongInt;

function BitToggle(const val: longint; const TheBit: byte): LongInt;

 

implementation

 

function IsBitSet(const val: longint; const TheBit: byte): boolean;

begin

result := (val and (1shl TheBit)) <> 0;

end;

 

function BitOn(const val: longint; const TheBit: byte): LongInt;

begin

result := val or (1shl TheBit);

end;

 

function BitOff(const val: longint; const TheBit: byte): LongInt;

begin

result := val and ((1shl TheBit) xor$FFFFFFFF);

end;

 

function BitToggle(const val: longint; const TheBit: byte): LongInt;

begin

result := val xor (1shl TheBit);

end;

 

end.

 

SetWord слово, которое необходимо установить.

BitNum номер бита, который необходимо выставить согласно определениям в секции const (Bit0, Bit1 и др.).

GetBitStat возвращает значение True, если бит установлен и False в противном случае.

 

Code:

const

Bit0 = 1;

Bit1 = 2;

Bit2 = 4;

Bit3 = 8;

Bit4 = 16;

Bit5 = 32;

Bit6 = 64;

Bit7 = 128;

 

Bit8 = 256;

Bit9 = 512;

Bit10 = 1024;

Bit11 = 2048;

Bit12 = 4096;

Bit13 = 8192;

Bit14 = 16384;

Bit15 = 32768;

 

procedure SetBit(SetWord, BitNum: Word);

begin

SetWord := SetWord Or BitNum; { Устанавливаем бит }

end;

 

procedure ClearBit(SetWord, BitNum: Word);

begin

SetWord := SetWord Or BitNum; { Устанавливаем бит }

SetWord := SetWord Xor BitNum; { Переключаем бит }

end;

 

procedure ToggleBit(SetWord, BitNum: Word);

begin

SetWord := SetWord Xor BitNum; { Переключаем бит }

end;

 

function GetBitStat(SetWord, BitNum: Word): Boolean;

begin

GetBitStat := SetWord and BitNum = BitNum; { Если бит установлен }

end;

 

 

Источник: Книга В. Озерова "Delphi. Советы программистов"

 

 

Code:

var

i: integer

s: string;

begin

s := '$' + ThatHexString;

i := StrToInt(a);

end;

 


 

Code:

const HEX: array['A'..'F'] of INTEGER = (10, 11, 12, 13, 14, 15);

var str: string;

Int, i: integer;

begin

READLN(str);

Int := 0;

for i := 1to Length(str) do

if str[i] < 'A'then

Int := Int * 16 + ORD(str[i]) - 48

else

Int := Int * 16 + HEX[str[i]];

WRITELN(Int);

READLN;

end.

 

 

 

Взято из Советов по Delphi отВалентина Озерова

Сборник Kuliba

Иногда возникают трудности интерпретации дробных чисел - что есть разделитель точка или запятая?

 

В Дельфи есть системные переменные:

DECIMALSEPARATOR - десятичный разделитель который принят в системе

THOUSANDSEPARATOR - разделитель тысяч, который принят в системе

 

Для USA регионального стандарта

DECIMALSEPARATOR будет "."

THOUSANDSEPARATOR будет ","

 

Для России

DECIMALSEPARATOR будет ","

THOUSANDSEPARATOR будет "." или " " (не помню уже)

 

Я перешел на Delphi 2.0 и у меня появилась проблема с типизированными файлами. У меня есть множество типизированных файлов с различными записями. Теперь, когда целое занимает 4 байта, определения всех моих записей должны быть изменены с расчетом на то, что вместо целого типа придется использовать тип SmallInts. Тем не менее, даже после такого изменения размер моих записей остается прежним...

 

Вам необходимо использовать модификатор "packed":

 

Code:

type

TMyRecType = packedrecord

...

end;

 

 

 

Автор: Steve Schafer

Были какие-то разговоры о том, что тип 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 - беззнаковое двойное слово.

 

Пояснение отJin X:

Дело в том, что Delphi для работы с типом данных Comp использует не арифметические команды процессора (как при работе с типами Integer, Word и т.п), а математический сопроцессор. Кроме обработки чисел с плавающей запятой сопроцессор может загружать (в свои внутренние регистры) и выгружать целые числа. Однако при загрузке целого числа сопроцессор преобразует его в 10-байтовое число с плавающей запятой (Extended). Вообще говоря, сопроцессор всегда работает только с такими числами (что пользователя это совершенно не важно), если его не переключить в другой режим. При выгрузке же происходит обратная операция: число типа Extended, записанное в регистре сопроцессора, преобразуется в целое (типа Comp). Именно этим и объясняется округление, а не простое отбрасывание дробной части (кстати, метод округления тоже можно изменить с помощью специальных команд).

 

 

Code:

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 < 0then 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 > 0then

Result := '-' + CompToStr(-C)

else

begin

Result := '';

Posn := 0;

while TRUE do

begin

Result := Char(Round($30 + CMod(C, 10))) + Result;

if C < 10then Break;

C := CDiv(C, 10);

Inc(Posn);

if Posn mod3 = 0then Result := ',' + Result;

end;

end;

end;

 

function CompToHex(C: Comp; Len: Integer): string;

begin

 

if (CompAsTwoLongs(C).HiL = 0) and (Len <= 8) then

Result := IntToHex(CompAsTwoLongs(C).LoL, Len)

else

Result := IntToHex(CompAsTwoLongs(C).HiL, Len - 8) +

IntToHex(CompAsTwoLongs(C).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))

elseif S[1] = '$'then{Шестнадцатиричная строка}

try

if Length(S) > 9then

begin

{Если строка некорректна, исключение сгенерирует StrToInt}

Result := StrToInt('$' + Copy(S, Length(S) - 7, 8));

if Result > l 0then Result := Result + Two32;

{Если строка некорректна, исключение сгенерирует StrToInt}

CompAsTwoLongs(Result).HiL :=

StrToInt(Copy(S, 1, Length(S) - 8))

end

else

begin

{Если строка некорректна, исключение сгенерирует StrToInt}

Result := StrToInt(S);

if Result < 0then 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.

 

 

 

Взято из Советов по Delphi

Code:

{ **** UBPFD *********** by kladovka.net ****

>> Конвертация : Римские -> арабские ; Арабские->Римские

 

Зависимости:

Автор: Gua, fbsdd ukr.net, ICQ:141585495, Simferopol

Copyright:

Дата: 03 мая 2002 г.

********************************************** }

 

Const

R: Array[1..13] ofString[2] =

('I','IV','V','IX','X','XL','L','XC','C','CD','D','CM','M');

A: Array[1..13] of Integer=

(1,4,5,9,10,40,50,90,100,400,500,900,1000);

 

..............

 

Function ArabicToRoman(N : Integer) : String; //Арабские в римские

Var

i : Integer;

begin

Result := '';

i := 13;

While N >0do

begin

While A[i] >N do Dec(i);

Result := Result + R[i];

Dec(N, A[i]);

end;

end;

В Дельфи есть предопределенные переменные языковых установок и форматов:

 

SysUtils

 

The following are a set of variables used to define the format for numeric or date/time strings:

 

var CurrencyString: string;

var CurrencyFormat: Byte;

var NegCurrFormat: Byte;

var ThousandSeparator: Char;

var DecimalSeparator: Char;

var CurrencyDecimals: Byte;

var DateSeparator: Char;

var ShortDateFormat: string;

var LongDateFormat: string;

var TimeSeparator: Char;

var TimeAMString: string;

var TimePMString: string;

var ShortTimeFormat: string;

 

var LongTimeFormat: string;

var ShortMonthNames: array[1..12] of string;

var LongMonthNames: array[1..12] of string;

var ShortDayNames: array[1..7] of string;

var LongDayNames: array[1..7] of string;

 

var SysLocale: TSysLocale;

var EraNames: array[1..7] of string;

var EraYearOffsets: array[1..7] of Integer;

var TwoDigitYearCenturyWindow: Word = 50;

 

var TListSeparator: Char;