Как Powershell округляет удваивается при умножении на строки? [Дубликат]

var funcs = [];
for (var i = 0; i < 3; i++) {      // let's create 3 functions
  funcs[i] = function(param) {          // and store them in funcs
    console.log("My value: " + param); // each should log its value.
  };
}
for (var j = 0; j < 3; j++) {
  funcs[j](j);                      // and now let's run each one to see with j
}
342
задан Hans Passant 18 May 2016 в 06:03
поделиться

15 ответов

Во-первых, это не будет ошибкой C # в любом случае - это будет ошибка .NET. C # - это язык - он не решает, как реализован Math.Round.

И, во-вторых, no - если вы читаете документы , вы увидите, что округление по умолчанию (округление до округления):

Возвращаемое значениеType: System.DoubleThe целое число, ближайшее a. Если дробная составляющая a находится на полпути между двумя целыми числами, одна из которых четная, а другая нечетная, то четное число возвращается. Обратите внимание, что этот метод возвращает Double вместо целочисленного типа.

Замечания. Поведение этого метода следует за стандартом IEEE 754, раздел 4. Этот вид округления иногда называется округлением до ближайшего или округления банкира.

Вы можете указать, как Math.Round должен округлить средние точки, используя перегрузку , чтобы избежать ошибки округления, которая возникает из-за постоянного округления среднего значения в одном направлении. который принимает значение MidpointRounding . Существует одна перегрузка с MidpointRounding, соответствующей каждой из перегрузок, которая не имеет одного:

Выполняется ли это по умолчанию был хорошо выбран или нет, это другое дело. (MidpointRounding был введен только в .NET 2.0. До этого я не уверен, что есть простой способ реализовать желаемое поведение, не делая этого самостоятельно.) В частности, история показала, что это не ожидаемый / g12] - и в большинстве случаев это кардинальный грех в дизайне API. Я вижу , почему Rounding Banker полезен ... но это все еще сюрприз для многих.

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

504
ответ дан Jon Skeet 28 August 2018 в 19:57
поделиться

с использованием пользовательского округления

public int Round(double value)
{
    double decimalpoints = Math.Abs(value - Math.Floor(value));
    if (decimalpoints > 0.5)
        return (int)Math.Round(value);
    else
        return (int)Math.Floor(value);
}
0
ответ дан anand360 28 August 2018 в 19:57
поделиться

Из MSDN, Math.Round (double a) возвращается:

Целое число, ближайшее a. Если дробная составляющая a находится на полпути между двумя целыми числами, одна из которых четная, а другая нечетная, то возвращается четное число.

... и поэтому 2.5, находясь на полпути между 2 и 3, округляется до четного числа (2). это называется округлением Banker (или округлым до четности) и является обычно используемым стандартом округления.

То же самое в статье MSDN:

] Поведение этого метода следует за стандартом IEEE 754, раздел 4. Этот вид округления иногда называется округлением до ближайшего или округления банкира. Это минимизирует ошибки округления, которые возникают из-за постоянного округления среднего значения в одном направлении.

Вы можете указать другое поведение округления, вызвав перегрузки Math.Round, которые принимают режим MidpointRounding .

39
ответ дан casperOne 28 August 2018 в 19:57
поделиться

По умолчанию MidpointRounding.ToEven, или округление банкиров ( 2.5 становится 2, 4.5 становится 4 и т. д. ) раньше меня поразило, записывая отчеты для учета, поэтому я напишу несколько слов о том, что я узнал, ранее и от изучения этого сообщения.

Кто такие банкиры, которые округляются по четным числам (возможно, британские банкиры!)?

Из wikipedia

Происхождение термина округления банкиров остается более неясным. Если этот метод округления всегда был стандартом в банковской деятельности, доказательства оказались чрезвычайно трудными для поиска. Напротив, раздел 2 доклада Европейской комиссии «Введение евро и округление валютных сумм» предполагает, что ранее не было стандартного подхода к округлению банковского дела; и он указывает, что суммы «на полпути» должны быть округлены.

Кажется, очень странный способ округления, особенно для банковских операций, если, конечно, банки не используют для приема большого количества депозитов даже суммы. Депозит £ 2,4 млн, но мы назовем его 2 млн фунтов стерлингов.

Стандарт IEEE 754 относится к 1985 году и дает оба способа округления, но с рекомендациями по стандарту банкира. Эта статья wikipedia имеет длинный список того, как языки реализуют округление (исправьте меня, если какое-либо из ниже сказанное неверно), и большинство из них не используют банкиров, но округление, которое вы преподаете в школе:

  • C / C ++ round () из math.h раундов от нуля (не округление банкира)
  • Java Math.Round округляется от нуля ( он наносит результат, добавляет 0.5, отбрасывает целое число). Есть альтернатива в BigDecimal
  • Perl использует аналогичный путь к C
  • Javascript такой же, как Java Math.Round.
23
ответ дан Community 28 August 2018 в 19:57
поделиться

Из MSDN:

По умолчанию Math.Round использует MidpointRounding.ToEven. Большинство людей не знакомы с «округлением до единого», поскольку альтернатива, «округление от нуля», чаще всего преподается в школе. .NET по умолчанию имеет значение «округление до четного», поскольку оно статистически превосходит, поскольку оно не разделяет тенденцию «округления от нуля» к округлению немного чаще, чем округляет его (при условии, что округленные числа имеют тенденцию быть положительными. )

http://msdn.microsoft.com/en-us/library/system.math.round.aspx

13
ответ дан Cristian Donoso 28 August 2018 в 19:57
поделиться

Вот как я должен был работать над этим:

Public Function Round(number As Double, dec As Integer) As Double
    Dim decimalPowerOfTen = Math.Pow(10, dec)
    If CInt(number * decimalPowerOfTen) = Math.Round(number * decimalPowerOfTen, 2) Then
        Return Math.Round(number, 2, MidpointRounding.AwayFromZero)
    Else
        Return CInt(number * decimalPowerOfTen + 0.5) / 100
    End If
End Function

Попытка с 1.905 с двумя десятичными знаками даст 1.91, как ожидалось, но Math.Round(1.905,2,MidpointRounding.AwayFromZero) дает 1.90! Метод Math.Round абсолютно несогласован и непригоден для большинства проблем, с которыми могут столкнуться программисты. Я должен проверить, вызвано ли (int) 1.905 * decimalPowerOfTen = Math.Round(number * decimalPowerOfTen, 2) тем, что я не хочу округлять то, что должно быть округлено вниз.

-1
ответ дан Developer 28 August 2018 в 19:57
поделиться

Вы должны проверить MSDN для Math.Round :

Поведение этого метода следует за стандартом IEEE 754, раздел 4. Этот вид округления иногда называют округлением до ближайшего или округления банкира.

Вы можете указать поведение Math.Round с помощью перегрузки:

Math.Round(2.5, 0, MidpointRounding.AwayFromZero); // gives 3

Math.Round(2.5, 0, MidpointRounding.ToEven); // gives 2
34
ответ дан Dirk Vollmar 28 August 2018 в 19:57
поделиться

Это уродливо, как и все ад, но всегда производит правильное арифметическое округление.

public double ArithRound(double number,int places){

  string numberFormat = "###.";

  numberFormat = numberFormat.PadRight(numberFormat.Length + places, '#');

  return double.Parse(number.ToString(numberFormat));

}
-2
ответ дан James Montagne 28 August 2018 в 19:57
поделиться

Silverlight не поддерживает параметр MidpointRounding. Ниже приведен метод расширения для Silverlight, который добавляет перечисление MidpointRounding:

public enum MidpointRounding
{
    ToEven,
    AwayFromZero
}

public static class DecimalExtensions
{
    public static decimal Round(this decimal d, MidpointRounding mode)
    {
        return d.Round(0, mode);
    }

    /// <summary>
    /// Rounds using arithmetic (5 rounds up) symmetrical (up is away from zero) rounding
    /// </summary>
    /// <param name="d">A Decimal number to be rounded.</param>
    /// <param name="decimals">The number of significant fractional digits (precision) in the return value.</param>
    /// <returns>The number nearest d with precision equal to decimals. If d is halfway between two numbers, then the nearest whole number away from zero is returned.</returns>
    public static decimal Round(this decimal d, int decimals, MidpointRounding mode)
    {
        if ( mode == MidpointRounding.ToEven )
        {
            return decimal.Round(d, decimals);
        }
        else
        {
            decimal factor = Convert.ToDecimal(Math.Pow(10, decimals));
            int sign = Math.Sign(d);
            return Decimal.Truncate(d * factor + 0.5m * sign) / factor;
        }
    }
}

Источник: http://anderly.com/2009/08/08/silverlight-midpoint-rounding-solution/

0
ответ дан jascur2 28 August 2018 в 19:57
поделиться

Поскольку Silverlight не поддерживает параметр MidpointRounding, вы должны написать свой собственный. Что-то вроде:

public double RoundCorrect(double d, int decimals)
{
    double multiplier = Math.Pow(10, decimals);

    if (d < 0)
        multiplier *= -1;

    return Math.Floor((d * multiplier) + 0.5) / multiplier;

}

Для примеров, в том числе о том, как использовать это как расширение, см. Сообщение: Окно .NET и Silverlight

3
ответ дан JBrooks 28 August 2018 в 19:57
поделиться

Простой способ:

Math.Ceiling(decimal.Parse(yourNumber + ""));
0
ответ дан Nalan Madheswaran 28 August 2018 в 19:57
поделиться

Характер округления

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

В общем или «арифметическом» округлении ясно, что 2.1, 2.2, 2.3 и 2.4 раунд 2,0; и 2,6, 2,7, 2,8 и 2,9 - 3,0.

Это оставляет 2,5, что не ближе к 2,0, чем к 3,0. Это зависит от вас, чтобы выбрать между 2.0 и 3.0, либо будет одинаково справедливым.

За минусом цифры -2,1, -2,2, -2,3 и -2,4 составят -2,0; и -2,6, 2,7, 2,8 и 2,9 составляли -3,0 при арифметическом округлении.

Для -2.5 необходим выбор между -2.0 и -3.0.

Другие формы округления

«Округление» принимает любое число с десятичными знаками и делает его следующим «целым» числом. Таким образом, не только 2.5 и 2.6 округляются до 3.0, но также делают 2.1 и 2.2.

Округление перемещает как положительные, так и отрицательные числа от нуля. Например. От 2,5 до 3,0 и от -2,5 до -3,0.

«Округление» сокращает число, сокращая ненужные цифры. Это приводит к перемещению чисел к нулю. Например. От 2,5 до 2,0 и от -2,5 до -2,0

В «округлении банкира» - в его наиболее распространенной форме - округленный округляемый округлый округлый округляющий округлый округлый округляющий округлый округлый округлый округляющий округлый округлый или округлый конец, так что результат округления всегда четное число. Таким образом, 2,5 раунда до 2,0, от 3,5 до 4,0, от 4,5 до 4,0, от 5,5 до 6,0 и т. Д.

«Альтернативное округление» изменяет процесс для любого .5 между округлением и округлением.

«Случайное округление» округляет a .5 вверх или вниз на совершенно случайной основе.

Симметрия и асимметрия

Функция округления называется «симметричной», если она либо округляет все числа от нуля или округляет все числа к нулю.

Функция является «асимметричной», если округляет положительные числа к нулю и отрицательные числа от нуля. 2,5-2,0; и -2,5 - -3,0.

Также асимметрична функция, которая округляет положительные числа от нуля и отрицательных чисел к нулю. Например. От 2,5 до 3,0; и -2,5 до -2,0.

Большинство людей думают о симметричном округлении, где -2,5 будут округлены до -3,0, а 3.5 будут округлены до 4.0. (в C # Round(AwayFromZero))

29
ответ дан Patrick Peters 28 August 2018 в 19:57
поделиться

Это называется округлением до четного (или округления банкира), что является действительной стратегией округления для минимизации начисленных ошибок в суммах (MidpointRounding.ToEven). Теория состоит в том, что если вы всегда будете округлять 0,5 числа в одном направлении, ошибки будут нарастать быстрее (от округлой до четности предполагается минимизировать это) (a).

Следуйте этим ссылкам для Описание MSDN:

  • Math.Floor , которое округляется вниз к отрицательной бесконечности.
  • Math.Ceiling , который округляется вверх до нуля.
  • Math.Truncate , который округляется вверх или вниз к нулю.
  • Math.Round , который округляется до ближайшего целого числа или заданного числа десятичных знаков. Вы можете указать поведение, если оно точно равноудалено между двумя возможностями, например округлением, чтобы окончательная цифра была четной («Round(2.5,MidpointRounding.ToEven)» становится равной 2) или так, что она находится дальше от нуля («Round(2.5,MidpointRounding.AwayFromZero)» становится 3).

Следующая диаграмма и таблица могут помочь:

-3        -2        -1         0         1         2         3
 +--|------+---------+----|----+--|------+----|----+-------|-+
    a                     b       c           d            e

                       a=-2.7  b=-0.5  c=0.3  d=1.5  e=2.8
                       ======  ======  =====  =====  =====
Floor                    -3      -1      0      1      2
Ceiling                  -2       0      1      2      3
Truncate                 -2       0      0      1      2
Round(ToEven)            -3       0      0      2      3
Round(AwayFromZero)      -3      -1      0      2      3

Обратите внимание, что Round намного мощнее, чем кажется, просто потому, что он может округлить до определенное количество знаков после запятой. Все остальные округляются до нуля десятичными знаками. Например:

n = 3.145;
a = System.Math.Round (n, 2, MidpointRounding.ToEven);       // 3.14
b = System.Math.Round (n, 2, MidpointRounding.AwayFromZero); // 3.15

С помощью других функций вы должны использовать метод умножения / деления для достижения такого же эффекта:

c = System.Math.Truncate (n * 100) / 100;                    // 3.14
d = System.Math.Ceiling (n * 100) / 100;                     // 3.15

(a) Конечно , эта теория зависит от того, что ваши данные имеют довольно равномерное распределение значений по четным половинам (0,5, 2,5, 4,5, ...) и нечетным половинам (1,5, 3,5, ...).

Если все равны «полузначениям» (например), ошибки будут накапливаться так же быстро, как если бы вы всегда округлялись.

177
ответ дан paxdiablo 28 August 2018 в 19:57
поделиться

У меня была эта проблема, когда мой SQL-сервер округлялся с 0,5 до 1, пока мое приложение C # этого не делало. Таким образом, вы увидите два разных результата.

Вот реализация с int / long. Это как Java-раунды.

int roundedNumber = (int)Math.Floor(d + 0.5);

Это, вероятно, самый эффективный метод, о котором вы могли бы подумать.

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

public double getRounding(double number, int decimalPoints)
{
    double decimalPowerOfTen = Math.Pow(10, decimalPoints);
    return Math.Floor(number * decimalPowerOfTen + 0.5)/ decimalPowerOfTen;
}

Вы можете ввести отрицательный десятичный знак для десятичных точек, и это также слово отлично.

getRounding(239, -2) = 200
2
ответ дан ShortFuse 28 August 2018 в 19:57
поделиться

У этой записи есть ответ, который вы ищете:

http://weblogs.asp.net/sfurman/archive/2003/03/07/3537.aspx

В основном это то, что он говорит:

Возвращаемое значение

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

Поведение этого метода следует за стандартом IEEE 754, раздел 4. Этот вид округления иногда называется округлением до ближайшего или округления банкира , Если цифры равны нулю, этот вид округления иногда называют округлением к нулю.

0
ответ дан Vaccano 28 August 2018 в 19:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: