当前位置:  开发笔记 > 编程语言 > 正文

没有条件,循环和算术运算符的C中的因子

如何解决《没有条件,循环和算术运算符的C中的因子》经验,为你挑选了6个好方法。

如何在C中找到数字的阶乘(从1到10),而不使用:

循环语句喜欢for,while和do while;

条件运算符,如if和case; 和

算术运算符如+, - ,*,%,/,++, - ?

仅供参考:我在C aptitude中找到了这个问题.



1> Brian R. Bon..:

因为它只有1到10,所以只需预先计算它并将其存储在一个大小为11的简单int数组中.对于数组中的第一个元素,放置1.它不是你问题的有效输入范围,但也可能是正确的.

我们需要存储11个元素而不是我们需要的10个元素,否则我们需要使用操作" - "来获得正确的索引.但是在您的问题中不允许减法.

int factorial(int x)
{
  return precomputedArray[x];
}


好吧,这隐式使用+因为arr [i]是*(arr + i);)
@Brian R. Bondy:实际上,阶乘被定义为n!= i的乘积,其中1 <= i <= n.那就是0!= i的乘积,其中1 <= i <= 0.没有我满足1 <= i <= 0所以0!减少为空产品.空产品等于一.空产品等于一的原因有几个.考虑i的乘积,其中1 <= i <= 10且我是偶数.该产物也等于2i的乘积,其中1 <= i <= 5且i是(2i-1)的乘积,其中1 <= i <= 5且i是偶数.但是最后一个产品是空的,所以必须保持平等.

2> Antti Huima..:

这是一个没有循环,算术或条件的解决方案,并且不依赖于预计算.它也没有使用短路条件语句像&&或者||它们是等效的做法if.所以这似乎是没有任何条件的第一个正确的解决方案.现在适当的C没有C++功能:)

#include 
#define uint unsigned int

void A(uint *a, uint *b)
{
    uint tmp = *a & *b;
    *a = (*a | *b) & ~tmp;
    *b = tmp << 1;
}

#define REPEAT32(s) \
s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s

uint add(uint a, uint b)
{
    REPEAT32(A(&a, &b);) return a;
}

uint bitexpand(uint b)
{
    b = (b << 1)  | b; b = (b << 2)  | b; b = (b << 4)  | b;
    b = (b << 8)  | b; b = (b << 16) | b;
    return b;
}

void M(uint *acc, uint *a, uint *b)
{
    *acc = add(*acc, *a & bitexpand(*b & 1));
    *a <<= 1;
    *b >>= 1;
}

uint mult(uint a, uint b)
{
    uint acc = 0;
    REPEAT32(M(&acc, &a, &b);) return acc;
}

uint factorial(int n)
{
    uint k = 1;
    uint result = 0;
    result |= (bitexpand(n == 1) & k);
    k = mult(k, 2); result |= (bitexpand(n == 2) & k);
    k = mult(k, 3); result |= (bitexpand(n == 3) & k);
    k = mult(k, 4); result |= (bitexpand(n == 4) & k);
    k = mult(k, 5); result |= (bitexpand(n == 5) & k);
    k = mult(k, 6); result |= (bitexpand(n == 6) & k);
    k = mult(k, 7); result |= (bitexpand(n == 7) & k);
    k = mult(k, 8); result |= (bitexpand(n == 8) & k);
    k = mult(k, 9); result |= (bitexpand(n == 9) & k);
    k = mult(k, 10); result |= (bitexpand(n == 10) & k);
    return result;
}

int main(int argc, char **argv)
{
    uint i;
    /* Demonstration loop, not part of solution */
    for (i = 1; i <= 10; i++)
    {
        printf("%d %d\n", i, factorial(i));
    }
}

更新:讨论中包含声称短路条件如&&在不使用if的解决方案中是可接受的.这是一个简单的宏,模仿双向'if'使用&&,显然使整个问题变得不那么有趣:

#define IF(i, t, e) \
(void)((i) && (goto then##__LINE__, 1)); goto else##__LINE__;
then##__LINE__: t; goto cont##__LINE__; \
else##__LINE__: e; cont##__LINE__: ((void)0);

然后你可以定义

#define WHILE(c, s) \
loop##__LINE__: IF(c, s; goto loop##__LINE__, ((void)0)))

然后问题的其余部分变得微不足道.



3> 小智..:
#include 

static const int factorial[] = {
    1,
    1,
    2,
    6,
    24,
    120,
    720,
    5040,
    40320,
    362880,
    3628800,
};

/* Test/demo program. */
int main(void)
{
    int i;

    for (i = 0; i <= 10; ++i)
        printf("%d %d\n", i, factorial[i]);

    return 0;
}

(任何使用这个答案来完成家庭作业问题的人都会失败,或者有一位具有良好幽默感的老师.)

(呸,我很慢.其他人已经给出了这个答案.请随意投票给他们答案.)



4> dsm..:

也许我正在解决某人的作业,但它看起来像一个有趣的挑战,无论如何,这是我的解决方案(编译警告,但不能帮助那些没有让它看起来丑陋(呃))

编辑:我已经改变了程序,使其支持相当长的阶乘(最多20个左右),并通过删除里面的查找表使代码更加整洁prev().

#include 
#include 

#define _if(CND, OP1, OP2) (((CND) && ((OP1) || 1)) || (OP2))

long long int add(long long int x, long long int y){
    long long int r = x ^ y;
    long long int c = x & y;
        c = c << 1;    
    _if(c != 0, r = add(r, c), 1);

    return r;
}

long long int prev(long long int x){
    return add(x, -1);
}                           

long long int mult(long long int x, long long int y){
    long long int r;

    _if(x == 0,
         r = 0,
       _if(x == 1, 
            r = y, 
            r = add(y, mult(prev(x), y))));

    return r;
}

long long int fac(long long int x){
    long long int r;

    _if(x < 2,
        r = 1,
        r = mult(x, fac(prev(x))));

    return r;
}

int main(int argc, char**argv){
    long long int i;

    for(i = 0; i <= 20; i++)
        printf("factorial(%lli) => %lli\n", i, fac(i));

    return 0;
}

样品运行:

[dsm@localhost:~/code/c]$ gcc -o proc proc.c
[dsm@localhost:~/code/c]$ ./proc #/
factorial(0) => 1
factorial(1) => 1
factorial(2) => 2
factorial(3) => 6
factorial(4) => 24
factorial(5) => 120
factorial(6) => 720
factorial(7) => 5040
factorial(8) => 40320
factorial(9) => 362880
factorial(10) => 3628800
factorial(11) => 39916800
factorial(12) => 479001600
factorial(13) => 6227020800
factorial(14) => 87178291200
factorial(15) => 1307674368000
factorial(16) => 20922789888000
factorial(17) => 355687428096000
factorial(18) => 6402373705728000
factorial(19) => 121645100408832000
factorial(20) => 2432902008176640000
[dsm@localhost:~/code/c]$



5> sharptooth..:

明确禁止使用"+"," - "和"*",但"+ ="," - ="和"*="不是,因此递归实现变为......

int factorial( int arg )
{
    int argcopy = arg;
    argcopy -= 1;
    return arg == 1 ? arg : arg *= factorial( argcopy );
}

在"编译为C源模式"时,VC7拒绝编译上面的内容 - 关于"*="的const L值,但是这里是另一个变体:

int factorial( int arg )
{
    int argcopy1 = arg;
    int argcopy2 = arg;
    argcopy1 -= 1;
    argcopy2 *= arg == 1 ? 1 : fact( argcopy1 );
    return argcopy2;
}



6> j_random_hac..:

这不是一个完整的答案,只是不同的方法add()mult()功能:

#define add(a, b)  sizeof (struct { char x[a]; char y[b]; })
#define mult(a, b) sizeof (struct { char x[a][b]; })

(我相信C,与C++不同,允许在一个内部定义新类型sizeof.)

这是add()基于指针算法的另一个(完全不可移植的)实现:

int add(int x, int y) {
    return (int) &((char*) x)[y];
}

推荐阅读
雯颜哥_135
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有