Недавно друг спросил, как можно узнать количество символов в числе, не переводя его в строку. Зачем ему это понадобилось, я так и не понял, вроде как задание такое получил. В общем, первое, что приходило на ум – это деление в цикле на 10, но это мне показалось не рационально. Немного подумав, пришел вот к такому простому решению, может, кому и пригодится XD
function Len(const X: Integer): Cardinal;
asm
CDQ // val := Abs(val); canned sequence
XOR EAX,EDX
SUB EAX,EDX
cmp EAX,0 // Check 0 Log10(0) error!!!
jz @zero
PUSH EAX
FLDLG2 // Log base ten of 2
FILD DWORD PTR [ESP]
FYL2X
FWAIT
SUB ESP,8 // Trunc
FNSTCW [ESP].Word // save
FNSTCW [ESP+2].Word // scratch
FWAIT
OR [ESP+2].Word, $0F00 // trunc toward zero, full precision
FLDCW [ESP+2].Word
FISTP qword ptr [ESP+4]
FWAIT
FLDCW [ESP].Word
POP ECX
POP EAX
POP EDX
@zero:
ADD EAX,1
end;
Суть сего действа такова:
- берем модуль числа
- проверяем, чтобы число было не ноль
- высчитываем десятичный логарифм данного числа
- обрезаем дробную часть
- инкрементируем его на единицу
Альтернативная запись:
function Len(const X: Integer): Cardinal; begin if (X <> 0) then Result:= Trunc(Log10(Abs(X))) + 1 else Result:= 1; end;
