Десятичные и математические операции
У меня есть простое преобразование a decimal
в С#. Это выглядит так:
private decimal BaseValue
{
get; set;
}
public decimal ConvertedValue
{
get
{
return BaseValue * (365 / 360);
}
}
Однако это не работает. Я предполагаю, что С# обрабатывает числа во фракции как целые числа. Поэтому я могу сделать это (что работает):
public decimal ConvertedValue
{
get
{
return BaseValue * (decimal)((double)365 / (double)360);
}
}
Теперь это похоже на перебор, но я могу жить с этим. Мой основной вопрос:
Почему Visual Studio предупреждает меня, что "Cast избыточен", для (double)
cast? И если я удаляю листинг (double)
, то приведение (decimal)
становится излишним. И если я удалю это, я вернусь к решению, которое не сработает. Помощь...?
Ответы
Ответ 1
один из способов решения этого вопроса - указать, что числа в вычислении decimal
с m
в конце
return BaseValue * (365m / 360m);
Почему Visual Studio предупреждает меня, что "Cast is redundant", для (двойного) литья
потому что когда у вас есть double
с одной стороны уравнения, тогда результат будет двойным.
(double)365 / (double)360
посмотрите документацию о перегрузках * оператора. Вы увидите, что операнды всегда одного типа:
decimal operator *(decimal x, decimal y);
... тогда (десятичная) литье становится излишней.
снова, потому что, когда у вас есть decimal
с одной стороны уравнения, тогда результат будет десятичным:
BaseValue * (decimal)(365 / 360)
Проблема здесь в области! вы отбрасываете весь результат деления на decimal
. На самом деле вы могли бы решить свою проблему просто, удалив круглые скобки:
return BaseValue * 365 / 360;
таким образом вы получите правильное уравнение, потому что результатом умножения *
будет decimal
(так как один из операндов - это decimal
, поэтому другой будет выполняться неявно), и снова результат деления также будет десятичным по той же причине.
Примечание:
Удаление скобок в общем случае не совпадает с тем, что их оставляют. В некоторых случаях операции с плавающей запятой отличаются результатом, когда порядок таких операций изменяется, хотя оба выражения математически идентичны. Комментарий Banex
EDIT:
Элемент m
называется литералом. Более подробную информацию о всех типах суффиксов или литералов можно найти в документации здесь
Ответ 2
Приведение decimal
избыточно, потому что компилятор знает, что вы хотите вернуть decimal
.
Один из двух прикладов double
избыточен, потому что, когда вы накладываете один из int
на a double
, ясно, что вы используете оператор деления double
вместо целочисленное деление.
Но этого достаточно, чтобы просто использовать буквенный суффикс decimal
m
:
return BaseValue * (365m / 360);
Опять же, одного m
достаточно, чтобы вывести правильный оператор.
Но hey, BaseValue
уже есть decimal
, и скобка не имеет смысла (если вы не хотите целочисленного divivsion)... это тоже должно работать:
return BaseValue * 365 / 360;
Ответ 3
вы можете просто добавить суффикс m к одному из чисел, чтобы сделать его десятичным:
return BaseValue * (365 / 360m);
Ответ 4
используйте суффикс m:
return 365m/360 * BaseValue;
Ответ 5
Существуют некоторые суффиксы для некоторых типов чисел, например:
// Use long suffix.
long l1 = 10000L;
// Use double suffix.
double d1 = 123.764D;
// Use float suffix.
float f1 = 100.50F;
// Use unsigned suffix.
uint u1 = 1000U;
// Use decimal suffix.
decimal m2 = 4000.1234M;
// Use unsigned suffix and long suffix.
ulong u2 = 10002000300040005000UL;
Суффиксы указывают типы номеров. Они инструктируют компилятор С#, что интегральный литерал, такой как 1000, считается определенным типом числа, например длинным (1000L). Мы рассмотрим, как добавить числовые суффиксы в числа.
В вашем случае:
public decimal ConvertedValue
{
get
{
return BaseValue * (365 / 360M);
}
}
А также более понятно, когда вы используете суффиксы Uppercase:
Нижеследующие суффиксы. Вы также можете указать строчные суффиксы, такие как u, l, ul, f, d и m. Но их легче путать с числами. Буква "l" иногда рассматривается как номер 1.
Ответ 6
Вам нужна только одна двойная броска. Итак,
return BaseValue * (decimal)(365/(double)360);
будет работать нормально.
Как только один является двойным, компилятор знает, как рассматривать его как нецелое деление.
Альтернативно
return (BaseValue*365)/360;
будет работать.
или даже
return BaseValue*365/360;
поскольку умножение имеет более высокий приоритет, чем деление.
Ответ 7
Вы можете просто использовать десятичные литералы, используя суффикс m
:
public decimal ConvertedValue
{
get
{
return BaseValue * (365m/360);
}
}
Причина, по которой второй листинг является избыточным, заключается в том, что С# выводит, что первое число (365) в вашем выражении ((double)365 / (double)360)
равно double
. Поэтому, чтобы вычислить деление, он будет трансформировать второй элемент в double
. Поэтому неважно, напишите ли вы (double)
как второй элемент:
csharp> (double) 365/350
1.04285714285714
csharp> (double) 365/ (double) 350
1.04285714285714
Тем не менее, совершенно бесполезно приводить к удвоениям, а затем вернуться к десятичным знакам. Используя один десятичный литерал в вашем выражении, другой номер также будет десятичным, и, таким образом, мы останемся в мире decimal
.
Ответ 8
В вашем примере вы можете просто оставить скобки прочь:
return BaseValue*365/360;
Ответ 9
Двойник, разделенный на двойной, (конечно) двойной. Таким образом, литье результата является избыточным.
Было бы короче, если бы вы просто указали числа как десятичные числа:
return BaseValue * (365m /360);
Ответ 10
Либо одна из (двойных) бросок избыточна, но не обе.
Если любой аргумент операции двойной, другой аргумент автоматически преобразуется в double.
Можете ли вы написать один из аргументов как константу реального числа, например, 365.0?