问题:

已知自然数e是一个无限不循环小数,则小数点后的某个位置可能会出现字符串“123456789”,现在想要求这个字符串的前一个数字是数字几。

思路:

首先明确e是如何计算出来的,由高中数学可知:
e.png

或者可以写成:
e1.png

很明显第一种我不知道怎么写,所以选择第二种,也就是计算阶乘!但是,选用什么数据类型来存储运算结果?已知结果是无限不循环小数,那么我们可以排除float和double,因为这两个精度没这么大。所以选择何种数据类型呢???选择百度吧!百度告诉我,应该选用BigDecimal类型。

BigDecimal简介:

  • BigDecimal是在java.math包中提供的API类,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理。一般情况下,对于那些不需要准确计算精度的数字,我们可以直接使用Float和Double处理,但是Double.valueOf(String) 和Float.valueOf(String)会丢失精度。所以开发中,如果我们需要精确计算的结果,则必须使用BigDecimal类来操作。
  • BigDecimal所创建的是对象,故我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象。

BigDecimal类的构造方法:

BigConstra.png

可以看到,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;
    }

}