Работа с числами
Прииспользованиифункции 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;
- Подробности
- Родительская категория: Язык программирования Дельфи
- Категория: Работа с числами
Страница 1 из 2