怎样求两数相除得到的小数的循环节?

SmallBoat2000 2010-01-06 08:46:04
怎样求两数相除得到的小数的循环节?
比如:input :1和6两个整数(1/6);
output: 循环节 :6

比如:
intput :1、7;
output:142857
...全文
978 18 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
ray194466 2011-04-28
  • 打赏
  • 举报
回复
循环小数分,混合循环小数,和纯循环小数。
我看提供接发的几位都没有考虑混合循环小数把。
SmallBoat2000 2010-01-08
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 longteng1116 的回复:]
//自己写的,欢迎纠错.

#include <iostream>
#include <string>
#include <vector>
using namespace std;

string fun(int x, int y)  //返回 x/y的循环节,如果无循环节,返回 ( 0 )
{
vector <bool> flag;
flag.assign(y,false);
for(int i = 0;i <y;i++)
flag[i] = false;
string temp = "";
int a =x%y; 
while( a != 0 && !flag[a])  //算法:如果遇到相同的商,那么后面的结果同样会再次重复,终止模拟。
{
      flag[a] = true;
  a *= 10;
  temp += a/y+'0';
  a = a%y;
}
if(a == 0) return "(0)";
char ch = a*10/y + '0';            //循环节头字符
int site = temp.find_first_of(ch);  //找循环节第一个字符
temp = temp.substr(site);
return '('+temp+')';
}
int main()
{
int x,y;
while(cin>>x>>y)
cout < <fun(x,y) < <endl;
}


[/Quote]
我改了一下:代码如下:

string fun(int x, int y) //返回 x/y的循环节,如果无循环节,返回 ( 0 )
{
vector <bool> flag;
flag.assign(y,false);
string left="";
string ret="";
int a =x%y;
while( a != 0 && !flag[a]) //算法:如果遇到相同的余数,那么后面的结果同样会再次重复,终止模拟。
{
left += a+'0';
flag[a] = true;
a *= 10;
ret += a/y+'0';
a = a%y;
}
if(a == 0) return "(0)";
char ch = a + '0'; //第一个相同余数
int site = left.find_first_of(ch); //找第一个相同余数
ret = ret.substr(site);
return '('+ret+')';
}
SmallBoat2000 2010-01-08
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 longteng1116 的回复:]
//自己写的,欢迎纠错.

#include <iostream>
#include <string>
#include <vector>
using namespace std;

string fun(int x, int y)  //返回 x/y的循环节,如果无循环节,返回 ( 0 )
{
vector <bool> flag;
flag.assign(y,false);
for(int i = 0;i <y;i++)
flag[i] = false;
string temp = "";
int a =x%y; 
while( a != 0 && !flag[a])  //算法:如果遇到相同的商,那么后面的结果同样会再次重复,终止模拟。
{
      flag[a] = true;
  a *= 10;
  temp += a/y+'0';
  a = a%y;
}
if(a == 0) return "(0)";
char ch = a*10/y + '0';            //循环节头字符
int site = temp.find_first_of(ch);  //找循环节第一个字符
temp = temp.substr(site);
return '('+temp+')';
}
int main()
{
int x,y;
while(cin>>x>>y)
cout < <fun(x,y) < <endl;
}


[/Quote]

有个bug啊!
knate 2010-01-08
  • 打赏
  • 举报
回复

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <map>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
int x,y;
cin>>x>>y;
if(! y){
cout<<"数据错误"<<endl;
return 0;
}

x %= y;//仅取小数部分

int t;
t = y;
for(;! (t%2);)
t /= 2;
for(;! (t%5);)
t /= 5;
if((t == 1) || (x == 0)){
cout<<"不是循环小数"<<endl;
system("pause");
return 0;
}

if( x < 0)
x = -x;
if(y < 0)
y = -y;
//不考虑负数


for(int a = x,b = y,k;;){
k = b % a;
if(! k){
x /= a;
y /= a;
k = a;
break;
}
a = k;
b = a;
}
//约分,感觉多余


cout<<"x/y"<<endl;
cout<<x<<"/"<<y<<endl;
map<int ,int > m;
vector<int> remaind;
for(int n = 0;;++ n){
if(m.find(x) == m.end()){
remaind.push_back( (10*x) / y);
m[x] = n;
x = (10*x) % y;
}else{
cout<<"循环节:";
for(vector<int>::iterator p = remaind.begin()+m[x];p != remaind.end();++p)
cout<<*p;
cout<<endl;
break;
}
}

system("pause");
return 0;
}
雪狐 2010-01-07
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 michael122 的回复:]
循环节的长度不会超过分母的值
拿1/7为例:
第1位:10/7=1 余 10 mod 7=3
第2位:30/7=4 余 30 mod 7=2
第3位:20/7=2 余 20 mod 7=6
第4位:60/7=8 余 60 mod 7=4
第5位:40/7=5 余 40 mod 7=5
第6位:50/7=7 余 50 mod 7=1

当余数等于分子的时候就结束了, 商的序列142857就是结果
当然,复杂度会比较大


[/Quote]

高!
alphaxiang 2010-01-07
  • 打赏
  • 举报
回复

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
unsigned int index;

void set_q(unsigned int q,unsigned char buf[])
{
if(q<10)
{
buf[index]='0'+q;
index++;
return;
}
else
{
set_q(q/10,buf);
set_q(q%10,buf);
return;
}
}

unsigned int Get_xhj(unsigned int m,unsigned int n,unsigned char Xhj[])
{
unsigned int *flag=(unsigned int*)malloc(n*sizeof(unsigned int));
memset(flag,0,n*sizeof(unsigned int));
index++;
unsigned int r,q;
q=m/n;
set_q(q,Xhj);
r=m-q*n;//余数,新的分母

while((r!=0)&&(flag[r]==0))//r==0,则整除,flag[r]!=0,则循环节已经出现
{
flag[r]=index;
q=(r*10)/n;
r=r*10-q*n;
set_q(q,Xhj);
}
Xhj[0]=flag[r];
free(flag);
return r;
}

int main()
{
index=0;
unsigned int i;
unsigned char data[20];
int m,n,r;
printf("Please input m and n,keep m is larger than n:\n");
scanf("%d %d",&m,&n);
r=Get_xhj(m,n,data);
if(r==0)
{
printf("m 可被n除尽\n");
return 0;
}
printf("循环节为:");
for(i=data[0];i<index;i++)printf("%c ",data[i]);
printf("\n%循环节长度:%d\n",index-data[0]);
return 0;
}

mLee79 2010-01-07
  • 打赏
  • 举报
回复
最平凡的(最慢的)实现:

#include <stdio.h>

typedef unsigned long ul;
#ifdef _MSC_VER
typedef __int64 int64;
#else
typedef long long int64;
#endif

int64 gcd( int64 a , int64 b )
{
while( a %= b )
if( 0 == (b %= a) )
return a;
return b;
}

void slove( int64 a , int64 b )
{
int c;
int64 x;
x = gcd( a , b ); a /= x; b /= x;
while(0==b%5) b/=5,a*=2;
while(0==b%2) b/=2,a*=5;
a %= b;
if(1!=b)
{
x = a;
do{
a *= 10;
c = (int)(a/b);
a %= b;
putchar( '0'+c );
} while(a!=x);
}
putchar('\n');
}

int main()
{
ul a , b ;
while( 2 == scanf( "%lu%lu" , &a , &b ) && 0 != b )
slove( a , b );
return 0;
}

michael122 2010-01-07
  • 打赏
  • 举报
回复
循环节的长度不会超过分母的值
拿1/7为例:
第1位:10/7=1 余 10 mod 7=3
第2位:30/7=4 余 30 mod 7=2
第3位:20/7=2 余 20 mod 7=6
第4位:60/7=8 余 60 mod 7=4
第5位:40/7=5 余 40 mod 7=5
第6位:50/7=7 余 50 mod 7=1

当余数等于分子的时候就结束了, 商的序列142857就是结果
当然,复杂度会比较大

alphaxiang 2010-01-07
  • 打赏
  • 举报
回复
存储结果改为动态分配内存:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
unsigned int index;

void set_q(unsigned int q,unsigned char buf[])//存储商到buf中
{
if(q<10)
{
buf[index]='0'+q;
index++;
return;
}
else
{
set_q(q/10,buf);
set_q(q%10,buf);
return;
}
}

int Get_xhj(unsigned int m,unsigned int n,unsigned char Xhj[])//计算循环节
{
unsigned int *flag=(unsigned int*)malloc(n*sizeof(unsigned int));
if(NULL==flag)
{
printf("Memory Error!\n");
return -1;
}
memset(flag,0,n*sizeof(unsigned int));
index++;
unsigned int r,q;
q=m/n;
set_q(q,Xhj);
r=m-q*n;//余数,同时作为新的分母

while((r!=0)&&(flag[r]==0))//r==0,则整除,flag[r]!=0,则循环节已经出现
{
flag[r]=index;//记录循环节起始位置
q=(r*10)/n;
r=r*10-q*n;
set_q(q,Xhj);
}
Xhj[0]=flag[r];
free(flag);
return r;
}

int main()
{
index=0;
unsigned int i;
unsigned char *data;
int m,n,r;
printf("Please input m and n:\n");
scanf("%d %d",&m,&n);

data=(unsigned char*)malloc(n*sizeof(unsigned char));
if(NULL==data)
{
printf("memory error\n");
return 0;
}

while(m<n)
{
m*=10;
}
r=Get_xhj(m,n,data);
if(r==0)
{
printf("m 可被n除尽\n");
return 0;
}
else if(r==-1)
{
printf("memory error\n");
return 0;
}
printf("循环节为:\n");
for(i=data[0];i<index;i++)printf("%c ",data[i]);
printf("\n%循环节长度:%d\n",index-data[0]);
return 0;
}


绿色夹克衫 2010-01-06
  • 打赏
  • 举报
回复
肯定低于分母的值,不过也不容忽视呀。
比如1/1000000007,印象中循环节长度恰好是1000000006,输出为字符串的话,就1G了。

[Quote=引用 7 楼 fancymouse 的回复:]
>循环节输出的话可能上G了!
至少不可能超过分母的值。输出要上G的话那10在b下的指数就要上G。这一般没那么杯具。
[/Quote]
  • 打赏
  • 举报
回复
[Quote=引用楼主 smallboat2000 的回复:]
怎样求两数相除得到的小数的循环节?
比如:input :1和6两个整数(1/6);
      output: 循环节 :6

比如:
intput :1、7;
output:142857
[/Quote]


看到这道题就我就来劲,迅雷笔试考过。

其实很简单,模拟除法。

不断得*10然后除以被除数,这里是7,每次结果存在数组里,之后对7求余,再*10,循环。
这个数组里存的就是2个数相除的小数点后的东东。

现在注意终止条件(也就是查找循环节),你是求循环位,需要用一个位图记录(可以用map),然后不断查找,当前数组里的元素是否与数组前面的某个元素相等,继续比较循环情况,检测出第一次循环,就输出之间的循环节,即可。


不知道说了这些你能理解清楚不。
FancyMouse 2010-01-06
  • 打赏
  • 举报
回复
>循环节输出的话可能上G了!
至少不可能超过分母的值。输出要上G的话那10在b下的指数就要上G。这一般没那么杯具。
_千鸟 2010-01-06
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 litaoye 的回复:]
这还真是个问题,别看有的时候数不大,循环节输出的话可能上G了!
[/Quote]

太大的也不会让你去求吧. 0~50的
1/2:(0)
1/3:0.(3)
1/4:(0)
1/5:(0)
1/6:0.1(6)
1/7:0.(142857)
1/8:(0)
1/9:0.(1)
1/10:(0)
1/11:0.(09)
1/12:0.08(3)
1/13:0.(076923)
1/14:0.0(714285)
1/15:0.0(6)
1/16:(0)
1/17:0.(0588235294117647)
1/18:0.0(5)
1/19:0.(052631578947368421)
1/20:(0)
1/21:0.(047619)
1/22:0.0(45)
1/23:0.(0434782608695652173913)
1/24:0.041(6)
1/25:(0)
1/26:0.0(384615)
1/27:0.(037)
1/28:0.03(571428)
1/29:0.(0344827586206896551724137931)
1/30:0.0(3)
1/31:0.(032258064516129)
1/32:(0)
1/33:0.(03)
1/34:0.0(2941176470588235)
1/35:0.0(285714)
1/36:0.02(7)
1/37:0.(027)
1/38:0.0(263157894736842105)
1/39:0.(025641)
1/40:(0)
1/41:0.(02439)
1/42:0.0(238095)
1/43:0.(023255813953488372093)
1/44:0.0(227)
1/45:0.0(2)
1/46:0.0(2173913043478260869565)
1/47:0.(0212765957446808510638297872340425531914893617)
1/48:0.0208(3)
1/49:0.(020408163265306122448979591836734693877551)
1/50:(0)
绿色夹克衫 2010-01-06
  • 打赏
  • 举报
回复
这还真是个问题,别看有的时候数不大,循环节输出的话可能上G了!
_千鸟 2010-01-06
  • 打赏
  • 举报
回复
发现多余代码
for(int i = 0;i <y;i++)
flag[i] = false;
主要是用vector方便调试。
_千鸟 2010-01-06
  • 打赏
  • 举报
回复
//自己写的,欢迎纠错.

#include<iostream>
#include<string>
#include<vector>
using namespace std;

string fun(int x, int y) //返回 x/y的循环节,如果无循环节,返回 ( 0 )
{
vector<bool> flag;
flag.assign(y,false);
for(int i = 0;i<y;i++)
flag[i] = false;
string temp = "";
int a =x%y;
while( a != 0 && !flag[a]) //算法:如果遇到相同的商,那么后面的结果同样会再次重复,终止模拟。
{
flag[a] = true;
a *= 10;
temp += a/y+'0';
a = a%y;
}
if(a == 0) return "(0)";
char ch = a*10/y + '0'; //循环节头字符
int site = temp.find_first_of(ch); //找循环节第一个字符
temp = temp.substr(site);
return '('+temp+')';
}
int main()
{
int x,y;
while(cin>>x>>y)
cout<<fun(x,y)<<endl;
}

FancyMouse 2010-01-06
  • 打赏
  • 举报
回复
>超过计算机精度就没办法了
为啥没办法?乃小学算术的办法忘了?
军爷_010 2010-01-06
  • 打赏
  • 举报
回复
用double类型保存结果,超过计算机精度就没办法了

33,027

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧