Algorithm 使用基于整数除法的例程计数-是否有公式化方法?
考虑一个通过连续除法和余数运算进行计数的例程 从64位被除数开始,例程除以常数除数。Algorithm 使用基于整数除法的例程计数-是否有公式化方法?,algorithm,language-agnostic,math,puzzle,Algorithm,Language Agnostic,Math,Puzzle,考虑一个通过连续除法和余数运算进行计数的例程 从64位被除数开始,例程除以常数除数。 如果余数为0,则例程返回。 否则,将余数乘以2^32,再加上整数商,即可生成新的红利 代码: /// ULong - 64 bit, unsigned /// UInt - 32 bit, unsigned const UInt Divisor; int TrickyCounter( ULong Dividend) { int count = 0; Ulong Quotient;
如果余数为0,则例程返回。
否则,将余数乘以2^32,再加上整数商,即可生成新的红利 代码:
/// ULong - 64 bit, unsigned
/// UInt - 32 bit, unsigned
const UInt Divisor;
int TrickyCounter( ULong Dividend)
{
int count = 0;
Ulong Quotient;
UInt Remainder;
do {
Quotient = Dividend/Divisor;
Remainder = Dividend%Divisor;
assert((Quotient >> 32) == 0);
count = count + 1;
Dividend = ((ULong)Remainder << 32) + Quotient;
} while (Remainder != 0);
return count;
}
///ULong-64位,无符号
///UInt-32位,无符号
常数除数;
int TrickyCounter(乌龙股息)
{
整数计数=0;
乌龙商;
单位余数;
做{
商=被除数/除数;
余数=股息%除数;
断言((商>>32)==0);
计数=计数+1;
股息=((ULong)余数0)
商=被除数/除数;
余数=股息%除数;
断言((商>>32)==0);
计数=计数-1;
股息=((ULong)余数
一些红利会导致这种循环永远持续吗
股息=0x1FFFFFL,除数=2是一个相当明显的例子,整个家族(除数)断言的确切目的是什么?另外,根据您的上一个问题,第二个代码段似乎不是您想要的。突然,有一个计数参数用于确定迭代次数,这显然使您上一个问题的答案为“否”。我为混淆道歉-最后一个文本应用于第一种形式,它没有其他退出条件。断言将商保持在2^32以下,以便有两个干净的片段合并在一起。
Uint TrickyNumber( ULong Dividend, int count)
{
Ulong Quotient = 0;
UInt Remainder;
while (count > 0)
Quotient = Dividend/Divisor;
Remainder = Dividend%Divisor;
assert((Quotient >> 32) == 0);
count = count - 1;
Dividend = ((ULong)Remainder << 32) + Quotient;
}
return (UInt)Quotient;
}
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
size_t tricky_counter( uint64_t dividend, const uint32_t divisor )
{
const size_t cycle_buffer_size = 1024;
size_t count = 0;
uint64_t quotient;
uint32_t remainder;
uint64_t pre[cycle_buffer_size];
do {
pre[ count % cycle_buffer_size ] = dividend;
quotient = dividend/divisor;
remainder = dividend%divisor;
if ( (quotient >> 32) != 0) {
printf("quotient: 0x%" PRIx64 "\n", quotient);
}
count = count + 1;
dividend = ((uint64_t)remainder << 32) + quotient;
for (size_t i = 0; i < count && i<cycle_buffer_size;++i) {
if (pre[i] == dividend) {
size_t cycle = 0;
printf("dividend repeats: \n");
while (i != count % cycle_buffer_size) {
//~ printf(" 0x%" PRIx64 " / %" PRId32 " \n", pre[i], divisor);
i = (i + 1) % cycle_buffer_size;
++cycle;
}
printf(" 0x%" PRIx64 " / %" PRId32 " cycle size %zd \n", dividend, divisor, cycle);
return 0;
}
}
} while (remainder != 0);
return count;
}
int main ( void )
{
for (uint64_t k = 1; k < 256; ++k)
for (uint64_t x = 2; x < 1024; ++x)
tricky_counter( (x-1 << 32) + 0x01010101L * k, x);
}