有谁知道一种在编译时计算C中至少两个数字的LCM(最小公倍数)和/或GCD(最大公分母)的机制( 不是C ++ ,我知道那里有模板魔术)?

我通常使用GCC并回想一下,当所有输入都已知时(例如:sin,cos等),它可以在编译时计算某些值。

我正在寻找如何在GCC中执行此操作(最好以其他编译器可以处理的方式),并希望相同的机制在Visual Studio中可以工作。

===============>>#1 票数:5

我想通了...

#define GCD(a,b) ((a>=b)*GCD_1(a,b)+(a<b)*GCD_1(b,a))
#define GCD_1(a,b) ((((!(b)))*(a)) + (!!(b))*GCD_2((b), (a)%((b)+!(b))))
#define GCD_2(a,b) ((((!(b)))*(a)) + (!!(b))*GCD_3((b), (a)%((b)+!(b))))
#define GCD_3(a,b) ((((!(b)))*(a)) + (!!(b))*GCD_4((b), (a)%((b)+!(b))))
#define GCD_4(a,b) ((((!(b)))*(a)) + (!!(b))*GCD_5((b), (a)%((b)+!(b))))
#define GCD_5(a,b) ((((!(b)))*(a)) + (!!(b))*GCD_6((b), (a)%((b)+!(b))))
#define GCD_6(a,b) ((((!(b)))*(a)) + (!!(b))*GCD_7((b), (a)%((b)+!(b))))
#define GCD_7(a,b) ((((!(b)))*(a)) + (!!(b))*GCD_8((b), (a)%((b)+!(b))))
#define GCD_8(a,b) ((((!(b)))*(a)) + (!!(b))*GCD_last((b), (a)%((b)+!(b))))
#define GCD_last(a,b) (a)

#define LCM(a,b) (((a)*(b))/GCD(a,b))


int main()
{
    printf("%d, %d\n", GCD(21,6), LCM(21,6));
    return 0;
}

请注意,根据整数的大小,您可能需要包括更多中间步骤(例如,GCD_9,GCD_10等)。

我希望这有帮助!

===============>>#2 票数:1

部分基于Kevin的答案,这是一个宏序列,对于常量值和运行时错误,编译时都会失败。

如果不能选择失败,也可以配置为引入非编译时间函数。

#define GCD(a,b) ( ((a) > (b)) ? ( GCD_1((a), (b)) ) : ( GCD_1((b), (a)) ) )

#define GCD_1(a,b) ( ((b) == 0) ? (a) : GCD_2((b), (a) % (b) ) )
#define GCD_2(a,b) ( ((b) == 0) ? (a) : GCD_3((b), (a) % (b) ) )
#define GCD_3(a,b) ( ((b) == 0) ? (a) : GCD_4((b), (a) % (b) ) )
#define GCD_4(a,b) ( ((b) == 0) ? (a) : GCD_5((b), (a) % (b) ) )
#define GCD_5(a,b) ( ((b) == 0) ? (a) : GCD_6((b), (a) % (b) ) )
#define GCD_6(a,b) ( ((b) == 0) ? (a) : GCD_7((b), (a) % (b) ) )
#define GCD_7(a,b) ( ((b) == 0) ? (a) : GCD_8((b), (a) % (b) ) )
#define GCD_8(a,b) ( ((b) == 0) ? (a) : GCD_9((b), (a) % (b) ) )
#define GCD_9(a,b) (assert(0),-1)

提防将其扩展得太大,即使它会提早终止,因为编译器必须在评估之前完全插入所有内容。

===============>>#3 票数:0

我意识到您只对C实现感兴趣,但我想还是应该对C ++和模板元编程发表评论。 我并不完全相信在C ++中这是可能的,因为您需要定义明确的初始条件才能终止递归扩展。

template<int A, int B>
struct GCD {
    enum { value = GCD<B, A % B>::value };
};

/*
Because GCD terminates when only one of the values is zero it is impossible to define a base condition to satisfy all GCD<N, 0>::value conditions
*/
template<>
struct GCD<A, 0> { // This is obviously not legal
    enum { value = A };
};

int main(void)
{
    ::printf("gcd(%d, %d) = %d", 7, 35, GCD<7, 35>::value);
}

对于C ++ 0x,这可能是可能的,但是并不确定%100。

  ask by community wiki translate from so

未解决问题?本站智能推荐:

7回复

无法理解C源代码,它不能在GCC中编译,而是在Visual C ++中编译

在GCC中我收到以下错误: aes.c:在函数'copy_block'中: aes.c:278:错误:需要左值作为递增操作数 aes.c:278:错误:需要左值作为递增操作数 这是一段代码: 我试图将其更改为可编译版本,但不幸的是,作为一名Java程序员,我不清
1回复

C编译器中的列主数组存储

是否有C编译器具有扩展功能,可以按列优先顺序而不是标准行优先顺序存储数组?
2回复

使用C99语言的未命名成员的结构的正确行为是什么?

#include <stdio.h> struct s {int;}; int main() { printf("Size of 'struct s': %i\n", sizeof(struct s)); return 0; } Microsoft C编
1回复

Visual C ++是否在GCC中提供与`__attribute __((别名))`具有相同功能的语言结构?

__attribute__((alias))表示: 别名(“目标”) alias属性使声明作为另一个符号的别名发出,必须指定该符号。 例如, 将f定义为__f的弱别名。 在C ++中,必须使用目标的受损名称。 如果__f未在同一翻译单元中定义,则会出错。
2回复

C编译器的表达式前/后增量评估[重复]

这个问题已经在这里有答案 : 4年前关闭。 为什么这些构造使用前后递增的未定义行为? (14个回答) 今天,我发现了一些东西,这让我非
6回复

编译对象的布局

有没有办法 - 就像用gcc -E查看预处理的结果一样,看看编译成目标文件后我的对象是什么样的? 我说的是GCC,但包括MSVC在内的解决方案没问题。
1回复

具有可变参数的嵌套宏确实可以在GCC中进行编译,但不能在MSVC中进行编译

我使用boost / preprocessor创建了一个宏来重复创建代码。 原因是我使用非常受限制的编译器在非常受限制的目标硬件上工作,该编译器不支持数组。 我想出的代码如下: # define ESC(...) __VA_ARGS__ # define IF_BODY(n, cond
2回复

修补C / C ++函数以仅返回而不执行

我想避免在大型项目中执行一个系统功能。 重新定义它或添加一些ifdef逻辑是不可能的。 所以我想将代码修补为仅ret操作。 这些功能是: 和: 因此,我需要在Visual C++编译器上修补第一个,在GCC编译器上修补第二个。 我可以直接在x86 / x64的_w
3回复

编译器之间的浮点二进制布局

我正在清理我们的一些网络代码,并用更明显的typedef(例如int32_t和uint16_t )替换各种整数类型( int , unsigned short ,...),我想知道在不同编译器之间可移植double和float是如何实现的。 我们正在发送类似于以下内容的结构: 到目前为
3回复

获取编译器理解的宏扩展值

我正在使用一个具有大量宏的代码库,这些宏在整个地方都已定义,未定义和重新定义。 令人惊讶的是,编译器仍然可以检查它们,因此无论如何都可以提取这种宏扩展结果,即 有没有办法为MSVC和GCC做到这一点?