Как умножить длинную на двойную - PullRequest
1 голос
/ 11 марта 2012

Извините, что задал такой вопрос новичку, но я не могу понять это.

У меня есть длинное целое число, которое я хотел бы разделить на 1,28, затем округлить его вверх или вниз до ближайшего целого числа.

long size = 24524343254;
double ratio = 1.28;
size = size * 1.28; //Error Cannot implicitly convert type 'double' to 'long'

Ответы [ 3 ]

5 голосов
/ 11 марта 2012

Вам нужно явно привести ваш двойной результат обратно к длинному (так как компилятор утверждает, что неявное преобразование не выполняется:

size = (long)Math.Round(size * 1.28);

Вам нужно Math.Round, если вы хотите округлить до ближайшего (естьособый случай, когда число для округления находится посередине между двумя числами, тогда оно округляется до ближайшего даже по умолчанию.) Вы можете просто привести результат обратно (long)(size * 1.28), если хотите округлить до 0.

Как@CodeInChaos указывает, что неявное приведение от длинного к двойному (size * 1.28 приведёт размер к двойному первому) может привести к потере точности, так как удваивает с точностью только 53 бита , но длинным является 64 бит

2 голосов
/ 11 марта 2012

Вы также можете рассмотреть возможность использования decimal.

size = (long)Math.Round(size * 1.28m);//note the m making the literal a decimal.

. В этой ситуации это дает два преимущества по сравнению с double:

  • decimal может представлять каждый long значение точно (в отличие от double, который имеет только 53 бита мантиссы, десятичное число имеет> 90 бит мантиссы, с достаточным для представления 63 битов, используемых long)
  • он может точно представлять 1,28.*

Вы также должны убедиться, что MidpointRounding.ToEven подходит для вас.Он округляет 1.5 до 2, но 0.5 до 0.

При использовании Decimal приведение к long, если значение выходит за пределы диапазона long, вызовет исключение.

При использовании double поведение переполнения зависит от режима.Если вы находитесь в разделе checked, он выдаст исключение, в контексте unchecked это приведет к неопределенному значению.Поскольку неопределенные значения редко желательны, я рекомендую использовать checked с double:

size = checked((long)Math.Round(size * 1.28));
2 голосов
/ 11 марта 2012

Вы должны разыграть результат как долго.

size = (long)Math.Round(size * 1.28);
...