2012-06-25 1 views
8

От http://msdn.microsoft.com/en-us/library/system.math.pow.aspxMath.pow принимает целое значение

int value = 2; 
for (int power = 0; power <= 32; power++) 
    Console.WriteLine("{0}^{1} = {2:N0}", 
         value, power, (long) Math.Pow(value, power)); 

Math.pow принимает двойников в качестве аргументов, но здесь мы переходим в Интс.

Вопрос: Есть ли опасность ошибок округления с плавающей запятой, если есть неявное преобразование в двойное событие?

Если да, то лучше использовать что-то вроде:

public static int IntPow(int x, uint pow) 
{ 
    int ret = 1; 
    while (pow != 0) 
    { 
     if ((pow & 1) == 1) 
      ret *= x; 
     x *= x; 
     pow >>= 1; 
    } 
    return ret; 
} 
+0

Связанный вопрос: http://stackoverflow.com/questions/383587/how-do-you-do-integer-exponentiation-in-c Некоторое хорошее чтение в этом вопросе и Ссылки по теме – dash

+0

См. также: http://stackoverflow.com/questions/936541/math-pow- – dash

+0

И [этот] (http://stackoverflow.com/questions/4297454/c-sharp-math-pow-is -неточно-расчетно) по ошибкам округления. –

ответ

3

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

Что касается использования альтернативного метода, который вы предлагаете, это специфично для приложения. Является ли ошибка округления с плавающей точкой абсолютно неприемлемой? Будете ли вы использовать числа, которые соответствуют int32 (для переполнения полномочий не требуется много?).

+2

Ошибка округления с плавающей точкой при преобразовании int в double? напишите больше об этом. –

+1

Это не просто преобразование int в double, оно превращает int в double, а затем делает с ним вещи. Как только вы начнете выполнять какие-либо операции (добавьте/размножаете/независимо), существует хотя бы вероятность ошибок округления. Так как повышение до мощности, вероятно, будет разбито на несколько добавлений/умножений, это увеличивает вероятность и величину ошибок с плавающей запятой. – Servy

+0

вы имеете в виду, поскольку они существуют с любым номером IEEE 754? –

-1
public static int IntPow(int number, uint power) 
     { 
      int result = 1; 
      for (int i = 0; i < power; i++) 
      { 
       result *= number; 
      } 
      return result; 
     } 

для читаемости!

+0

Есть причина для дополнительного кода - этот ответ - «O (мощность)», а код в вопросе «O (log (power)). –

5

Нет, нет ошибки округления, вызванной преобразованием в double. double может точно представлять все целые числа, попадающие в область степенной функции.

5

В вашем специальном случае, когда вы вычисляете 2 на мощность x, вы можете использовать простой сдвиг влево. Это позволит упростить код:

public static int TwoPowX(int power) 
{ 
    return (1<<power); 
} 
+0

И в плавающей точке полномочия двух можно тривиально вычислить с помощью 'ldexp'. Какой .NET нет, но довольно легко писать, используя «BitConverter.Int64BitsToDouble». –