二次规划的舍入问题

Posted

技术标签:

【中文标题】二次规划的舍入问题【英文标题】:Rounding Issue with Quadratic Program 【发布时间】:2019-01-10 02:49:25 【问题描述】:

在我正在练习的一个问题中,目标是写出二次表达式,然后将其四舍五入到千分之一位。这是所需的输出:

1(a 变量) 6(b 变量) 3(c 变量)

4(a 变量) 10(b 变量) 6.1(c 变量)

输出: -0.551, -5.449(顶行的答案)

-1.056, -1.444(底线答案)

问题不在于如何解决问题,而在于我得到的答案。计算二次方程时如下:

      double a = scan.nextDouble(); 
      double b = scan.nextDouble(); 
      double c = scan.nextDouble(); 

      //equation is correct
      double answer1 = 0.001 * Math.floor((-b + Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a)* 1000.0) ;
      double answer2 = 0.001 * Math.floor((-b - Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a) * 1000.0);

我得到的答案是正确的,除了当我开始四舍五入到千分位时,有些数字是正确的,而另一些则不是,即使看起来它们只是根据问题正确四舍五入。

我的输出: -0.551, -5.45 -1.057, -1.444

这与我的四舍五入方式有关吗?任何有关理解此舍入问题的帮助将不胜感激:)

【问题讨论】:

"当我开始 rounding" 是什么让您认为 Math.floorroundingMath.round 将是 rounding 的方法。 【参考方案1】:

https://floating-point-gui.de/languages/java/

如何舍入

获取字符串:

String.format("%.2f", 1.2399) // returns "1.24"
String.format("%.3f", 1.2399) // returns "1.240"
String.format("%.2f", 1.2) // returns "1.20"

打印到标准输出(或任何 PrintStream):

System.out.printf("%.2f", 1.2399) // same syntax as String.format()

如果您不想要尾随零:

new DecimalFormat("0.00").format(1.2)// returns "1.20"
new DecimalFormat("0.##").format(1.2)// returns "1.2"

如果需要特定的舍入模式:

new BigDecimal("1.25").setScale(1, RoundingMode.HALF_EVEN); // returns 1.2

如果您确实需要对实际数字进行四舍五入,而不仅仅是打印输出:

  double result = Math.round(value * scale) / scale;

其中scale 可能固定为1000 三位小数或计算任意小数位:

  int scale = (int) Math.pow(10, precision);

【讨论】:

如何取整:使用Math.round(),而不是Math.floor() 这可能也会有所帮助。 :-) 但通常当人们谈论舍入浮点数时,他们实际上是指舍入输出,即打印结果。

以上是关于二次规划的舍入问题的主要内容,如果未能解决你的问题,请参考以下文章

等式约束的二次规划问题

MPC的终结——二次规划求解约束极值问题

MATLAB 二次规划函数的使用以及扩展

MATLAB 二次规划函数的使用以及扩展

MATLAB 二次规划函数的使用以及扩展

二次规划问题