电子商务网站建站目的/推广平台网站热狗网
黄金分割数0.61803... 是个无理数,这个常数十分重要,在许多工程问题中会出现。有时需要把这个数字求得很精确。
对于某些精密工程,常数的精度很重要。也许你听说过哈勃太空望远镜,它首次升空后就发现了一处人工加工错误,对那样一个庞然大物,其实只是镜面加工时有比头发丝还细许多倍的一处错误而已,却使它成了“近视眼”!!
言归正传,我们如何求得黄金分割数的尽可能精确的值呢?有许多方法。
比较简单的一种是用连分数:
1
黄金数 = ---------------------
1
1 + -----------------
1
1 + -------------
1
1 + ---------
1 + ...
这个连分数计算的“层数”越多,它的值越接近黄金分割数。
请你利用这一特性,求出黄金分割数的足够精确值,要求四舍五入到小数点后100位。
小数点后3位的值为:0.618
小数点后4位的值为:0.6180
小数点后5位的值为:0.61803
小数点后7位的值为:0.6180340
(注意尾部的0,不能忽略)
你的任务是:写出精确到小数点后100位精度的黄金分割值。
注意:尾数的四舍五入! 尾数是0也要保留!
显然答案是一个小数,其小数点后有100位数字,请通过浏览器直接提交该数字。
注意:不要提交解答过程,或其它辅助说明类的内容。
计算结果(101位):0.61803398874989484820458683436563811772030917980576286213544862270526046281890244970720720418939113748
答案(100位然后四舍五入):0.6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911375
思路:
1,观察式子,可以得出从一项开始,往后的分别是1/1,1/2,2/3,3/5,5/8,刚好是斐波那契数列的两项之比;
2,因为题目求的是精确到100位,当fn/f(n+1)往后继续计算,100位也是不变的(所以n是多少?),(如果求斐波那契数列,使用递归式,层数太深(栈会溢出),要使用递推式);
3,因为long long存不了100位,不能使用c语言自带的整数进行计算,因此需要使用大数计算;
参考代码:
#include<iostream>
#include<string>
#include<algorithm>
#include<sstream>
using namespace std;
int n = 400;// void i2s(int num, string &str){// }string add(string a, string b){a = a.substr(a.find_first_not_of('0'));//去掉开头的零b = b.substr(b.find_first_not_of('0'));long long lenA = a.length();long long lenB = b.length();long long len = max(lenA,lenB) + 10;//有可能A、B长度相同,相加后进一位reverse(a.begin(), a.end()); //反转便于低位逐步求和reverse(b.begin(), b.end());string ans(len,'0'); //初始化答案为len长,全部为字符0for (int i = 0; i < lenA; ++i)//把a拷贝到ans中{ans[i] = a[i];}int temp = 0; //temp是上一位相加后的进位for (int i = 0; i < len; ++i){if(i < b.length()){temp += (ans[i] - '0') + (b[i] - '0');}else{temp += (ans[i] - '0');}ans[i] = temp % 10 + '0';temp /= 10;}reverse(ans.begin(), ans.end());return ans.substr(ans.find_first_not_of('0'));
}int cmp(string a, string b){unsigned long i1 = a.find_first_not_of('0');unsigned long i2 = b.find_first_not_of('0'); if(i1 == string::npos) a = '0';else a.substr(i1);if(i2 == string::npos) b = '0';else b.substr(i2);if(a.length() > b.length()) return 1;else if(a.length() < b.length()) return -1;else{ //长度相等if(a < b) return -1;if(a > b) return 1;else return 0;}
}//此处a一定大于等于b
string subtract(string a, string b){//完整减法里,a可以小于b,这结果为负数,交换ab进行下面的代码//反转reverse(a.begin(), a.end());reverse(b.begin(), b.end());//按位做减法for (int i = 0; i < b.length(); ++i){if(a[i] >= b[i]){a[i] = a[i] - b[i] + '0'; }else{//小了就要借位int k = 1;while(a[i + k] == '0') {//这里可以保证i+k这一位不是0a[i + k] = '9';k++;}a[i + k] = a[i + k] - '1' + '0';a[i] = (a[i] - '0' + 10) - (b[i] - '0') + '0';}}reverse(a.begin(), a.end());if(a.find_first_not_of('0') == string::npos) return "0";return a.substr(a.find_first_not_of('0'));
}//除法作为减法
string devide(string a, string b){
//只考虑 a < b 的情况string ans = "0.";//转化为减法for (int i = 0; i < 101; ++i){a.append("0");int t = 0;while(cmp(a,b) >= 0){ //a > ba = subtract(a, b); //不停地做减法t++;//记录减法做了多少次}string t_str;//i2s(t ,t_str); //is2()是windows特有的库函数stringstream stream;stream << t;stream >> t_str;ans.append(t_str);}return ans;
}int main(int argc, char const *argv[])
{string a = "1";string b = "1";//cout<<devide(a,b)<<endl;for (int i = 3; i <= n; ++i)//求斐波那契数列{string temp = b;b = add(a,b);a = temp;// cout<<b <<" "<<endl;}string ans = devide(a,b);cout<<ans <<endl;cout<<ans.length() - 2 <<endl;return 0;
}