Странное поведение функции pow

Во время выполнения следующих строк кода:

int i,a;    

for(i=0;i<=4;i++)  
{    
    a=pow(10,i);    
    printf("%d\t",a);    
}   

Я был удивлен, увидев результат, он выходит 1109910009999 вместо 110100100010000,

В чем может быть причина?

Заметка
Если вы думаете, что это погрешность с плавающей запятой, что в приведенном выше цикле для i = 2, значения хранятся в переменной a является 99,

Но если вы напишите вместо

a=pow(10,2);

теперь значение выходит 100, Как это возможно?

5 ответов

Я даже не могу произнести c, но я могу сказать вам, почему.

Вы установили a быть int, pow() генерирует число с плавающей запятой, которое в НЕКОТОРЫХ случаях может быть на волосок меньше 100 или 10000 (как мы видим здесь).

Затем вы складываете это в целое число, которое ОБРАЩАЕТСЯ в целое число. Таким образом, вы потеряете эту дробную часть. К сожалению. Если вы действительно нуждались в целочисленном результате, раунд может быть лучшим способом сделать эту операцию.

Будьте осторожны даже там, так как для достаточно больших полномочий ошибка может быть достаточно большой, чтобы вызвать сбой, что даст вам то, чего вы не ожидаете. Помните, что числа с плавающей запятой несут только такую ​​большую точность.

Функция pow() возвращает double, Вы назначаете это переменной aтипа int, Это не "округляет" значение с плавающей запятой, оно усекает его. Так pow() возвращает что-то вроде 99.99999... за 10^2, а потом вы просто отбрасываете часть.9999... Лучше сказать a = round(pow(10, i)),

Это связано с неточностью с плавающей запятой. Хотя вы проходите вints они неявно преобразуются в тип с плавающей запятой, так какpow Функция определена только для параметров с плавающей запятой.

Никто не объяснил, как на самом деле сделать это правильно - вместо pow Функция, просто есть переменная, которая отслеживает текущую мощность:

int i, a, power;    

for (i = 0, a = 1; i <= 4; i++, a *= 10) {    
    printf("%d\t",a);    
}

Это продолжающееся умножение на десять гарантированно даст вам правильный ответ, и вполне нормально (и намного лучше, чем pow, даже если бы он давал правильные результаты) для задач, таких как преобразование десятичных строк в целые числа.

Математически целочисленная степень целого числа является целым числом.

В хорошем качестве pow() рутина этот конкретный расчет не должен приводить к ошибкам округления. Я запустил ваш код на Eclipse/Microsoft C и получил следующий вывод:

1   10  100 1000    10000   

Этот тест НЕ показывает, использует ли Microsoft числа с плавающей запятой и округления, или они определяют тип ваших чисел и выбирают подходящий метод.

Итак, я запустил следующий код:

#include <stdio.h>
#include <math.h>
main ()
{
    double i,a;

    for(i=0.0; i <= 4.0 ;i++)
    {
        a=pow(10,i);
        printf("%lf\t",a);
    }
}

И получил следующий вывод:

1.000000    10.000000   100.000000  1000.000000 10000.000000    
Другие вопросы по тегам