Круглый номер с RoundingMode.HALF_EVEN [дубликат]

На самом деле все зависит от того, для чего вам нужна случайная генерация, но вот мое занятие.

Сначала создайте автономный метод для генерации случайного числа. Обязательно допустим ограничения.

public static int newRandom(int limit){
    return generatedRandom.nextInt(limit);  }

Затем вам нужно создать очень простую структуру принятия решений, которая сравнивает значения. Это можно сделать одним из двух способов. Если у вас есть очень ограниченное количество чисел для проверки, достаточно простого оператора IF:

public static int testDuplicates(int int1, int int2, int int3, int int4, int int5){
    boolean loopFlag = true;
    while(loopFlag == true){
        if(int1 == int2 || int1 == int3 || int1 == int4 || int1 == int5 || int1 == 0){
            int1 = newRandom(75);
            loopFlag = true;    }
        else{
            loopFlag = false;   }}
    return int1;    }

Вышеприведенное сравнивает int1 с int2 через int5, а также гарантирует отсутствие нулей в randoms.

Используя эти два метода, мы можем сделать следующее:

    num1 = newRandom(limit1);
    num2 = newRandom(limit1);
    num3 = newRandom(limit1);
    num4 = newRandom(limit1);
    num5 = newRandom(limit1);

Followed:

        num1 = testDuplicates(num1, num2, num3, num4, num5);
        num2 = testDuplicates(num2, num1, num3, num4, num5);
        num3 = testDuplicates(num3, num1, num2, num4, num5);
        num4 = testDuplicates(num4, num1, num2, num3, num5);
        num5 = testDuplicates(num5, num1, num2, num3, num5);

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

Надеюсь, это поможет. Этот сайт мне очень помог, я чувствовал себя обязанным, по крайней мере, ПОПРОБОВАТЬ, чтобы помочь.

84
задан elm 4 December 2015 в 10:53
поделиться

10 ответов

Вы можете использовать scala.math.BigDecimal :

BigDecimal(1.23456789).setScale(2, BigDecimal.RoundingMode.HALF_UP).toDouble

Существует ряд других режимов округления , которые, к сожалению, не очень хорошо (хотя их эквиваленты Java являются ).

103
ответ дан Travis Brown 15 August 2018 в 22:23
поделиться
  • 1
    Скорее всего, я бы сказал. Все, что связано с сетями или финансами, может потребовать округления, а также производительности. – Rex Kerr 19 June 2012 в 21:33
  • 2
    Полагаю, есть люди, для которых длинный призыв к неуклюжей библиотеке более понятен, чем простая математика. Я бы рекомендовал "%.2f".format(x).toDouble в этом случае. Только в 2 раза медленнее, и вам нужно использовать только те библиотеки, которые вы уже знаете. – Rex Kerr 19 June 2012 в 21:52
  • 3
    @RexKerr, вы не округлите в этом случае .. просто обрезаете. – José Leal 27 September 2012 в 07:59
  • 4
    @ JoséLeal - А? scala> "%.2f".format(0.714999999999).toDouble res13: Double = 0.71, но scala> "%.2f".format(0.715).toDouble res14: Double = 0.72. – Rex Kerr 20 April 2013 в 19:37
  • 5
    @RexKerr Я предпочитаю ваш string.format путь, но в локалях s.a. (финский), следует позаботиться о том, чтобы исправить локаль ROOT. Например. & quot;%. 2f ".formatLocal (java.util.Locale.ROOT, x) .toDouble. Кажется, формат использует ',' из-за локали, тогда как toDouble не может принять его и бросает исключение NumberFormatException. Это, конечно, основано на том, где ваш код находится run , а не там, где он разработан. – akauppi 19 September 2014 в 11:02

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

scala> 1.23456789 - (1.23456789 % 0.01)
res4: Double = 1.23
28
ответ дан akauppi 15 August 2018 в 22:23
поделиться
  • 1
    Не рекомендовал бы это, хотя это мой собственный ответ: те же проблемы с неточностями, о которых упоминал @ryryguy в комментарии другого ответа, здесь тоже влияют. Используйте string.format с языком Java ROOT (я прокомментирую это там). – akauppi 19 September 2014 в 10:59
  • 2
    это идеально, если вам просто нужно отобразить значение и никогда не использовать его в последующих операциях. благодаря – Alexander Arendar 3 December 2014 в 22:20
  • 3
    вот что-то смешное: 26.257391515826225 - 0.057391515826223094 = 26.200000000000003 – kubudi 9 July 2015 в 14:37

Как насчет:

 val value = 1.4142135623730951

//3 decimal places
println((value * 1000).round / 1000.toDouble)

//4 decimal places
println((value * 10000).round / 10000.toDouble)
7
ответ дан blue-sky 15 August 2018 в 22:23
поделиться
  • 1
    довольно чистое решение. Вот мой для усечения: ((1.949 * 1000).toInt - ((1.949 * 1000).toInt % 10)) / 1000.toDouble не испытывал его слишком много, хотя. Этот код будет делать 2 десятичных знака. – robert 30 March 2016 в 07:45

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

Rounding
Java Formatter: Elapsed Time: 105
Scala Formatter: Elapsed Time: 167
BigDecimal Formatter: Elapsed Time: 27

Truncation
Scala custom Formatter: Elapsed Time: 3 

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

object TestFormatters {

  val r = scala.util.Random

  def textFormatter(x: Double) = new java.text.DecimalFormat("0.##").format(x)

  def scalaFormatter(x: Double) = "$pi%1.2f".format(x)

  def bigDecimalFormatter(x: Double) = BigDecimal(x).setScale(2, BigDecimal.RoundingMode.HALF_UP).toDouble

  def scalaCustom(x: Double) = {
    val roundBy = 2
    val w = math.pow(10, roundBy)
    (x * w).toLong.toDouble / w
  }

  def timed(f: => Unit) = {
    val start = System.currentTimeMillis()
    f
    val end = System.currentTimeMillis()
    println("Elapsed Time: " + (end - start))
  }

  def main(args: Array[String]): Unit = {

    print("Java Formatter: ")
    val iters = 10000
    timed {
      (0 until iters) foreach { _ =>
        textFormatter(r.nextDouble())
      }
    }

    print("Scala Formatter: ")
    timed {
      (0 until iters) foreach { _ =>
        scalaFormatter(r.nextDouble())
      }
    }

    print("BigDecimal Formatter: ")
    timed {
      (0 until iters) foreach { _ =>
        bigDecimalFormatter(r.nextDouble())
      }
    }

    print("Scala custom Formatter (truncation): ")
    timed {
      (0 until iters) foreach { _ =>
        scalaCustom(r.nextDouble())
      }
    }
  }

}
3
ответ дан cevaris 15 August 2018 в 22:23
поделиться
  • 1
    Дорогой scalaCustom не округляет, он просто усекает – Ravinder Payal 5 January 2018 в 14:37
  • 2
    hmm, OP не был специфичен для округления или усечения; ...truncate or round a Double. – cevaris 8 January 2018 в 19:19
  • 3
    Но, на мой взгляд, сравнение скорости / времени выполнения функции усечения с функциями округления является недостаточным. Вот почему я попросил вас разъяснить читателю, что пользовательская функция только усекает. Упомянутая вами функция усечения / пользовательской функции может быть упрощена. val doubleParts = double. toString.split («.») Теперь получите первые два символа doubleParts.tail и concat со строками ». & quot; и doubleParts. head и разобрать вдвое. – Ravinder Payal 9 January 2018 в 04:56
  • 4
    обновлено, лучше выглядеть? также ваше предложение toString.split(".") и doubleParts.head/tail может быть связано с дополнительным распределением массива и конкатенацией строк. однако, нужно будет проверить. – cevaris 10 January 2018 в 22:27

Я бы не использовал BigDecimal, если вы заботитесь о производительности. BigDecimal преобразует числа в строку и затем анализирует их снова:

  /** Constructs a `BigDecimal` using the decimal text representation of `Double` value `d`, rounding if necessary. */
  def decimal(d: Double, mc: MathContext): BigDecimal = new BigDecimal(new BigDec(java.lang.Double.toString(d), mc), mc)

Я буду придерживаться математических манипуляций, поскольку предложил Kaito .

3
ответ дан Community 15 August 2018 в 22:23
поделиться
  • 1
    Кроме того, вы можете использовать подход @ rex-kerr для питания вместо Math.pow – Khalid Saifullah 18 May 2013 в 05:22

Немного странно, но приятно. Я использую String, а не BigDecimal

def round(x: Double)(p: Int): Double = {
    var A = x.toString().split('.')
    (A(0) + "." + A(1).substring(0, if (p > A(1).length()) A(1).length() else p)).toDouble
}
0
ответ дан jafed 15 August 2018 в 22:23
поделиться

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

import scala.math._

object ExtNumber extends App {
  implicit class ExtendedDouble(n: Double) {
    def rounded(x: Int) = {
      val w = pow(10, x)
      (n * w).toLong.toDouble / w
    }
  }

  // usage
  val a = 1.23456789
  println(a.rounded(2))
}
3
ответ дан Mitrakov Artem 15 August 2018 в 22:23
поделиться
  • 1
    Просьба указать, что этот метод предназначен только для обрезания и не округления. – bobo32 25 May 2017 в 16:10

Изменить: исправлена ​​проблема, о которой указал @ryryguy. (Спасибо!) [/ ​​G0]

Если вы хотите, чтобы это было быстро, Kaito имеет правильную идею. math.pow медленнее. Для любого стандартного использования вам будет лучше с рекурсивной функцией:

def trunc(x: Double, n: Int) = {
  def p10(n: Int, pow: Long = 10): Long = if (n==0) pow else p10(n-1,pow*10)
  if (n < 0) {
    val m = p10(-n).toDouble
    math.round(x/m) * m
  }
  else {
    val m = p10(n).toDouble
    math.round(x*m) / m
  }
}

Это примерно в 10 раз быстрее, если вы находитесь в диапазоне Long (т.е. 18 цифр), чтобы вы могли округлить где-то между 10 ^ 18 и 10 ^ -18.

7
ответ дан Rex Kerr 15 August 2018 в 22:23
поделиться
  • 1
    Остерегайтесь, умножая на обратное, не работает надежно, потому что это может быть ненадежно представимо как double: scala> def r5(x:Double) = math.round(x*100000)*0.000001; r5(0.23515) == & gt; res12: Double = 0.023514999999999998. Вместо этого разделите значение: math.round(x*100000)/100000.0 – ryryguy 19 April 2013 в 23:37

Вот еще одно решение без BigDecimals

Truncate:

(math floor 1.23456789 * 100) / 100

Round:

(math rint 1.23456789 * 100) / 100

Или для любого двойного n и точности p:

def truncateAt(n: Double, p: Int): Double = { val s = math pow (10, p); (math floor n * s) / s }

Аналогично может быть сделано для функции округления, на этот раз с использованием currying:

def roundAt(p: Int)(n: Double): Double = { val s = math pow (10, p); (math round n * s) / s }

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

def roundAt2(p: Int) = roundAt(2)(p)
62
ответ дан Shonzilla 15 August 2018 в 22:23
поделиться
  • 1
    roundAt2 должен быть def roundAt2 (n: Double) = roundAt (2) (n) нет? – C4stor 8 September 2014 в 14:38
  • 2
    это, кажется, возвращает неверный результат для NaN, не так ли? – jangorecki 18 July 2016 в 23:42
  • 3
    проблема с floor заключается в том, что truncateAt(1.23456789, 8) вернет 1.23456788, а roundAt(1.23456789, 8) вернет правильное значение 1.23456789 – Todor Kolev 23 April 2017 в 21:25
3
ответ дан Community 5 September 2018 в 22:08
поделиться
Другие вопросы по тегам:

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