Comment detail

分数を小数に展開 (Nested Flatten)
Cでがんばってみたあんなに短くなるほかの言語がうらやましい。
もっと効率のいい書き方ないかなぁ。
循環小数の判定がむずかしい。。。
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
#include <stdio.h>
#include <string.h>
#include <assert.h>

int cal(char *ans, size_t bufsize, int a, int b)
{
    const char * const head   = ans;
    char       *jyunkan_start = NULL;  // 循環の始点
    const char *match_start   = NULL; // 
    size_t      match_count   = 0;

    memset(ans, '\0', bufsize);

    a = (a % b) * 10; 
    for( size_t n=1; n<bufsize; n ++, ans ++ )
    {
        // 計算
        *ans = '0' + a / b;
        a = (a % b) * 10;
        if( a == 0 ) break;

        /**********************/
        /* 循環小数のチェック */
        /**********************/
        if( match_start == NULL )
        {
            if( jyunkan_start == NULL )
            {
                jyunkan_start = ans;
                continue;
            }
            if( *jyunkan_start == *ans )
            {
                // 循環の開始位置かもしれない
                match_start = ans;
                match_count ++;
            }
        }
        else
        {
            // 循環の可能性あり
            if( *(jyunkan_start+match_count) == *ans )
            {
                if( (size_t)(match_start-jyunkan_start)==match_count)
                {
                    // ロジック上開始位置がずれるので巻き戻し
                    while( head != jyunkan_start )
                    {
                        if( *(jyunkan_start-1) == *(ans-1))
                        {
                            jyunkan_start --;
                            ans --;
                        }
                        else 
                        {
                            break;
                        }
                    }
                    // 循環部分を {}
                    memmove(jyunkan_start+1, jyunkan_start, match_count);
                    jyunkan_start[0] = '{';
                    jyunkan_start[match_count+1] = '}';
                    jyunkan_start[match_count+2] = '\0';
                    break;
                }
                match_count ++;
            }
            else
            {
                // はずれ
                jyunkan_start ++;
                match_start = NULL;
                match_count = 0;
            }
        }
    }

    return 0;
}

int main(int argc, char *argv[])
{
    char   ans[64]; // 循環する小数部の倍以上必要
    struct {
        int a, b;
        char ans[64];
    } 
    test[] = 
    {
        {  1,  2, "5" },
        {  1,  3, "{3}" },
        {  1,  7, "{142857}" },
        {  3, 14, "2{142857}" },
        { 50, 51, "{9803921568627450}" },
        { 13, 191,"068062827225130890052356020942408376963350785340314136125654450" }
    };

    for( size_t n=0; n<sizeof(test)/sizeof(*test); n++)
    {
        cal(ans, sizeof(ans), test[n].a, test[n].b); 
        printf("ans=0.%s\n", ans);
        assert( strcmp(ans, test[n].ans) == 0 );
    }
    return 0;
}
別にいいやと放置していたらバグだったorz
1
2
3
4
5
- 36: match_count ++;
+ 36: match_count = 1;

- 71: jyunkan_start ++;
+ 71: jyunkan_start = ans;

Index

Feed

Other

Link

Pathtraq

loading...