Взгляните на реализацию Apache Commons класса Tailer . Кажется, что он также обрабатывает вращение журнала.
Почему вы находите это удивительным? Ничто не мешает компилятору поддерживать 64-, 128- или более-битные целочисленные типы на 32-битной машине. Компилятор может даже поддерживать 57- и 91-битные типы, если это так. На практике поддержка 2N-битной целочисленной арифметики на N-битной машине является относительно простой задачей, поскольку набор команд типичной машины часто разрабатывается с учетом такого рода функциональности.
Это работает, потому что 64-битные целочисленные типы данных являются частью спецификации языка .
Компилятор для языка ДОЛЖЕН позволять вам работать с 64-разрядными целыми числами (и, конечно, получать правильные результаты).
Ваша программа должна работать (и работать точно так же), независимо от того, нацелены ли вы на 64-битную, 32-битную, 16-битную или 8-битную машину (что позволяет компилятор).
Кто бы ни написал компилятор, он должен был сделать все, что нужно , чтобы каждый поддерживаемый тип данных работал на на каждом целевом типе процессора.
Поддержка потенциально «более высоких» типов данных уже была решена , так что вам не придется делать это самостоятельно.
Как?
Очевидно, что принятие кода, который управляет 16-разрядными арифметическими операциями, и преобразование его в машинный код, работающий на 16-разрядном (или более высоком) процессоре, является «легкой» работой для компилятора, почти прямой перевод. Z = X + Y
может переводиться как mov a,(X); add a,(Y); mov (Z),a;
.
И наоборот, принять код, который управляет 64-разрядными арифметическими операциями, и преобразовать его в машинный код, который выполняется на 32-разрядном (или более низком) процессоре, является более сложным. Компилятору предстоит проделать больше работы, работая с 32-битными фрагментами каждого операнда за раз. Есть и другие способы сделать это.
Полученный машинный код может использовать несколько встроенных инструкций (больший код, более быстрое выполнение). Z = X + Y
может переводиться как mov a,(X); adc a,(Y); mov (Z),a; mov a,CARRY; adc a,(X+1); adc a,(Y+1); mov (Z+1),a;
.
Полученный машинный код может вызывать расширенные арифметические подпрограммы (меньший код, более медленное выполнение). Z = X + Y
может переводиться как mov a,X; call GET64; mov a,Y; call ADD64; mov a,Z; call STORE64;
.
Точно так же 32-битная арифметика работала в 16-битных системах.
В этом случае он использует 2 32-битных адреса памяти, чтобы вместе сформировать 64-битное число. Сложение / вычитание - это просто, вы делаете это по частям, единственная проблема - перенос переноса из нижней части в верхнюю. Для умножения / деления это сложнее (т.е. больше инструкций).
Это очевидно медленно, немного медленнее, чем 32-битная арифметика для умножения, но если вам это нужно, она есть для вас. А когда вы переходите на 64-битный процессор компилятор, он автоматически оптимизируется до одной инструкции с большим размером слова.
Реализация 64-битного умножения в Visual Studio 2010 Professional на 32-битном процессоре, скомпилированная в режиме выпуска, выглядит так:
_allmul PROC NEAR
A EQU [esp + 4] ; stack address of a
B EQU [esp + 12] ; stack address of b
mov eax,HIWORD(A)
mov ecx,HIWORD(B)
or ecx,eax ;test for both hiwords zero.
mov ecx,LOWORD(B)
jnz short hard ;both are zero, just mult ALO and BLO
mov eax,LOWORD(A)
mul ecx
ret 16 ; callee restores the stack
hard:
push ebx
A2 EQU [esp + 8] ; stack address of a
B2 EQU [esp + 16] ; stack address of b
mul ecx ;eax has AHI, ecx has BLO, so AHI * BLO
mov ebx,eax ;save result
mov eax,LOWORD(A2)
mul dword ptr HIWORD(B2) ;ALO * BHI
add ebx,eax ;ebx = ((ALO * BHI) + (AHI * BLO))
mov eax,LOWORD(A2) ;ecx = BLO
mul ecx ;so edx:eax = ALO*BLO
add edx,ebx ;now edx has all the LO*HI stuff
pop ebx
ret 16 ; callee restores the stack
Как видите, это НАМНОГО медленнее, чем обычное умножение.