тригонометрические функции (Sin
, Cos
и тому подобное) периодическая с периодом 2 пи (2 * Math.PI
). Однако, поскольку Math.PI
является double
и, таким образом, имеет 16-17 правильные цифры только вы не можете вычислить 1e27
наивным (мы требуем, по крайней мере, 27 цифр):
Double result = Math.Cos(1e27); // totally wrong.
Чтобы выполнить задачу, необходимо первое соответствующее значение pi
, например отсюда
http://www.piday.org/million/
И мы должны работать с BigInteger
, а также:
int exponent = 27;
const String piString = "314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316527120190914564856692346034861045432664821339360726024914127372458700660631558817488152092096282925409171536436789259036001133053054";
BigInteger pi2 = BigInteger.Parse(piString) * 2;
int scale = piString.Length - 1; // 2 * pi is not that big integer, it's 6.28...
BigInteger argument = BigInteger.Pow(10, exponent + scale);
// Now let's compute the double value (fraction) that's reminder of 1e27 % (2 * PI)
String remainder = (argument % pi2)
.ToString()
.PadLeft(piString.Length, '0')
.Insert(1, "."); // we can have x.xxx, 0.xxx, 0.0xxx etc. remainders
Double fraction =
Double.Parse("0." + remainder.Substring(0, 20), CultureInfo.InvariantCulture);
// and now, finally
Double result = Math.Cos(fraction);
Наконец, фактический результат
-0,695977596990354
Примечание, что naive C++ вычисление (взято из Qwertiy комментарий, который является 0.849247
), является абсолютно неправильным, поскольку даже C++ double
не поддерживает pi
27 цифр.
Точно как [задокументировано] (https://msdn.microsoft.com/en-us/library/system.math. cos (v = vs.110) .aspx): «Допустимые значения * d * варьируются от приблизительно -9223372036854775295 до приблизительно 9223372036854775295. Для значений вне этого диапазона метод Cos возвращает * d * неизменным, а не бросает исключение». –
Вы не можете «исправить» исходные методы, поскольку они были задокументированы так, чтобы они функционировали следующим образом. Тем не менее, вы можете создать свои собственные методы Cos и Sin, которые больше походят на то, что вы ожидаете. –
@ LasseV.Karlsen - вам также придется вводить другой тип данных, чем 'double' здесь. Я подозреваю, почему они не поддерживают более высокие значения, вы уже находитесь в точке, где отсутствие точности означает, что разные между последовательными представляемыми значениями больше, чем π –