Высокая мощность и двойная точность

Как вы решаете приведенное ниже уравнение на каком-либо языке по вашему выбору?

(1-1/X)^Y

Легко!

Но как насчет того, когда X & Y очень большие и X>>Y

например

(1-1/X)^Y
where 
X = 10^40
Y = 10^12

Похоже, это должно быть достаточно простой проблемой, но я не смог разобраться с проблемой двойной точности перед подачей питания.

2 ответа

Что ж, (1 - 1/X)^Y = exp(Y*log(1 - 1/X)), Если X очень большой и намного больше, чем Y, вы можете приблизить логарифм с

log(1 - 1/x) = -1/x -1/(2*X^2) + O(1/X^3)

и рассчитать

exp(-(Y/X+ Y/(2*X*X)))

Если X не намного больше, чем Yиспользование третьего или даже четвертого члена ряда Тейлора логарифма может быть необходимым.

С использованием GNU Octave расчеты являются приблизительными:

octave:1> x = 10^40
x =  1.0000e+40
octave:2> y = 10^12
y =  1.0000e+12
octave:3> (1-1/x)^y
ans =  1

octave:8> exp(-(y/x + y /(2*x*x)))
ans =  1

При условии, что вычисления, сделанные Даниэлем Фишером, верны, код для расчета exp(-(Y/X+ Y/(2*X*X))) в Java с использованием BigDecimal это:

public static void main(String[] args) {
    BigDecimal x = new BigDecimal(10,MathContext.UNLIMITED).pow(40);
    BigDecimal y = new BigDecimal(10,MathContext.UNLIMITED).pow(12);

    BigDecimal twoXSquared = new BigDecimal(2,MathContext.UNLIMITED).multiply(x).multiply(x);
    BigDecimal yDividedByTwoXSquared = y.divide(twoXSquared);

    BigDecimal yDividedByX = y.divide(x);


    BigDecimal exponent = new BigDecimal(-1,MathContext.UNLIMITED).multiply(yDividedByX.add(yDividedByTwoXSquared));
    System.out.println(exponent.toEngineeringString());

    BigDecimal result = new BigDecimal(Math.E,MathContext.UNLIMITED).pow(exponent.intValue());

    System.out.println(result.toEngineeringString());

}
Другие вопросы по тегам