问题:
已知自然数e是一个无限不循环小数,则小数点后的某个位置可能会出现字符串“123456789”,现在想要求这个字符串的前一个数字是数字几。
思路:
首先明确e是如何计算出来的,由高中数学可知:
或者可以写成:
很明显第一种我不知道怎么写,所以选择第二种,也就是计算阶乘!但是,选用什么数据类型来存储运算结果?已知结果是无限不循环小数,那么我们可以排除float和double,因为这两个精度没这么大。所以选择何种数据类型呢???选择百度吧!百度告诉我,应该选用BigDecimal类型。
BigDecimal简介:
- BigDecimal是在java.math包中提供的API类,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理。一般情况下,对于那些不需要准确计算精度的数字,我们可以直接使用Float和Double处理,但是Double.valueOf(String) 和Float.valueOf(String)会丢失精度。所以开发中,如果我们需要精确计算的结果,则必须使用BigDecimal类来操作。
BigDecimal所创建的是对象,故我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象。
BigDecimal类的构造方法:
可以看到,BigDecimal有很多构造方法,但是据说常用的就红框里的那几个
BigDecimal类的常用方法:
- add(BigDecimal)
BigDecimal对象中的值相加,返回BigDecimal对象
- subtract(BigDecimal)
BigDecimal对象中的值相减,返回BigDecimal对象
- multiply(BigDecimal)
BigDecimal对象中的值相乘,返回BigDecimal对象
- divide(BigDecimal)
BigDecimal对象中的值相除,返回BigDecimal对象
- toString()
将BigDecimal对象中的值转换成字符串
- doubleValue()
将BigDecimal对象中的值转换成双精度数
- floatValue()
将BigDecimal对象中的值转换成单精度数
- longValue()
将BigDecimal对象中的值转换成长整数
- intValue()
将BigDecimal对象中的值转换成整数
本题中用到了add(),devide(),multiply(),toString()四个方法
具体实现代码:
import java.math.BigDecimal;
import static java.math.BigDecimal.ROUND_HALF_DOWN;
public class CalculateE {
public static void main(String[] args) {
int index = 7000;
getE(10);
while (true) {
String str = getE(index).toString();
if (str.contains("123456789")) {
System.out.println(str.indexOf("123456789"));
break;
}
index += 1000;
System.out.println("开始查找"+index+"位内是否存在");
}
}
public static BigDecimal factorial(int n) {//求阶乘
BigDecimal t = new BigDecimal(1);
BigDecimal i = new BigDecimal(2);
BigDecimal j = new BigDecimal(3);
for (int a = 0; a < n - 2; a++) {
i = i.multiply(j);
j = j.add(t);
}
return i;
}
public static BigDecimal getE(int n) {
final BigDecimal temp = new BigDecimal(1);
BigDecimal e = new BigDecimal(2);
for (int i = 2; i < n; i++) {
e = e.add(temp.divide(factorial(i), n, ROUND_HALF_DOWN));
}
return e;
}
}