Недавно друг спросил, как можно узнать количество символов в числе, не переводя его в строку. Зачем ему это понадобилось, я так и не понял, вроде как задание такое получил. В общем, первое, что приходило на ум – это деление в цикле на 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;