Длина числа o_O

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