分数到小数

给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以字符串形式返回小数。

如果小数部分为循环小数,则将循环的部分括在括号内。

示例 1:

输入: numerator = 1, denominator = 2
输出: "0.5"

示例 2:

输入: numerator = 2, denominator = 1
输出: "2"

示例 3:

输入: numerator = 2, denominator = 3
输出: "0.(6)"
 

思路是碰到重复的被除数就说明进入了死循环。然后把它转换成我们要的格式。(不熟悉C语言字符串的话这部分真的很蛋疼)

注:一开始觉得是碰到重复余数,但实际不行,比如1/6,前两次余数都是4。

 

//当时的废话

但是由于我一开始用的是一个长度根据被除数确定的hash表,所以碰到INT_MIN的时候,内存不够了。。。再改。。。然后就是把小数部分和整数部分结合的时候。。。如果是循环小鼠的话,需要在循环部分加 ( ) 。这一段代码弄了很久。。。主要是之前写的贼几把乱。。脑子也贼几把乱。。。最后就是溢出的问题。。。真特么蛋疼。。。总之下面是我的代码,还是很乱。。但至少跑出来了,用时4ms。。。最下面是大佬的代码。。

 

//int转s字符串
char
* i2a(int num) { char *s=(char *)malloc(sizeof(char)*12); int i=0,j=0; unsigned n; if(num<0) { n=(unsigned)-num; s[i++]='-'; j++; } else n=(unsigned)num; do { s[i++]=n%10+'0'; n/=10; } while(n); s[i--]=0; char tmp; while(j<i) { tmp=s[j]; s[j++]=s[i]; s[i--]=tmp; } return s; } int contain(int *visited,int x,int size) { int i; for(i=0;i<size;i++) if(visited[i]==x) return i+1; return 0; } char* fractionToDecimal(int numerator, int denominator) { long long x,y; int i,j,pos,size=0,flag; x=numerator<0?(unsigned)-numerator:numerator; y=denominator<0?(unsigned)-denominator:denominator; flag=(numerator<0)^(denominator<0); char *integer; if(numerator==INT_MIN&&denominator==-1) { integer=i2a(INT_MAX); integer[9]='8'; } else integer=i2a(numerator/denominator); int *visited=(int *)malloc(sizeof(int)*10000); char *decimal=(char *)malloc(sizeof(char)*10000); memset(visited,0,sizeof(int)*10000); memset(decimal,0,sizeof(char)*10000); x=x%y; while(x) { if((pos=contain(visited,x,size))) break; visited[size]=x; x*=10; decimal[size++]=x/y+'0'; x%=y; } if(!size) return integer; decimal[size]='\0'; int inlen=strlen(integer); if(integer[0]=='0'&&flag) { integer[0]='-'; integer[1]='0'; integer[2]='\0'; inlen++; } int delen=strlen(decimal); char *rs=(char *)malloc(sizeof(char)*(inlen+delen+4)); for(i=0;i<inlen;i++) rs[i]=integer[i]; rs[inlen]='.'; if(x) { for(i=1;i<pos;i++) rs[inlen+i]=decimal[i-1]; rs[inlen+pos]='('; for(i-=1,j=0;i<delen;j++) rs[inlen+pos+1+j]=decimal[i++]; rs[inlen+delen+2]=')'; rs[inlen+delen+3]='\0'; } else { for(i=0;i<delen;i++) rs[inlen+1+i]=decimal[i]; rs[inlen+delen+1]='\0'; } return rs; }

 

这是用时最短的大佬的代码。

char* fractionToDecimal(int numerator, int denominator) {
    int base[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
    int map[1096] = {0};
    char tmp[1096];
    int p = 0;
    int sign = (numerator < 0) ^ (denominator < 0);
    long n1 = numerator < 0 ? -((long)numerator) : (long)numerator;
    long n2 = denominator < 0 ? -((long)denominator) : (long)denominator;
    
    if (sign && numerator) {
        tmp[p++] = '-';
    }

    long integer = n1 / n2;
    if (integer) {
        int i = 9;
        while (integer / base[i] == 0) {
            i--;
        }
        while (i >= 0) {
            tmp[p++] = integer / base[i] + '0';
            integer %= base[i];
            i--;
        }
    } else {
        tmp[p++] = '0';
    }
 
    long frac = n1 % n2;
    int repeat = 0;
    if (frac) {
        tmp[p++] = '.';
    }

    while (frac) {  
        int find = 0;
        for (int i = 0; i < p; i++) {
            if (map[i] == frac) {
                find = i;
                break;
            }
        }
        if (find) {
            repeat = find;
            break;
        } else {
            map[p] = frac;  
        }
        tmp[p++] = frac * 10 / n2 + '0';
        frac = (frac * 10) % n2;
    }
    tmp[p] = '\0';

    int returnsize = p;
    if (repeat) {
        returnsize += 2;    
    }
    char *ret = (char *)malloc(sizeof(char) * returnsize);
    
    if (repeat) {
        strncpy(ret, tmp, repeat);
        ret[repeat] = '(';
        strcpy(ret + repeat + 1, tmp + repeat);
        ret[p + 1] = ')';
        ret[p + 2] = '\0';
    } else {
        strcpy(ret, tmp);
    }
    return ret;
}
posted @ 2018-07-29 18:53  onlyandonly  阅读(641)  评论(0编辑  收藏  举报