Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/EmptyTag/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中计算两个long的百分比的溢出安全方法_Java - Fatal编程技术网

Java中计算两个long的百分比的溢出安全方法

Java中计算两个long的百分比的溢出安全方法,java,Java,我有两个非负长。它们可能很大,接近Long.MAX_值。我想从这两个数字中计算一个百分比 通常我会这样做: long numerator = Long.MAX_VALUE / 3 * 2; long denominator = Long.MAX_VALUE; int percentage = (int) (numerator * 100 / denominator); System.out.println("percentage = " + percentage

我有两个非负长。它们可能很大,接近Long.MAX_值。我想从这两个数字中计算一个百分比

通常我会这样做:

    long numerator = Long.MAX_VALUE / 3 * 2;
    long denominator = Long.MAX_VALUE;

    int percentage = (int) (numerator * 100 / denominator);
    System.out.println("percentage = " + percentage);
如果分子在Long.MAX_值的两个数量级范围内,则这是不正确的

正确、简单、快速的方法是什么

int percentage = (int) (0.5d + ((double)numerator/(double)denominator) * 100);

如果将
long
long
相除,将得到
long
,这对百分比不好。

简单的方法是在进行计算之前将两者都转换为
float
double
,但会略微降低精度。与其他选择相比,它也很慢

一种方法是将每个值分成两个32位的分量,然后进行长乘法和长除法。

我会使用:

int percentage = (int)(numerator * 100.0 / denominator + 0.5);

100.0
强制浮点数学从该点开始,并且
+0.5
舍入到最接近的整数,而不是截断。

除非我遗漏了一些明显的东西,否则你就不能写:

public class round {
  public static void main(String[] argv) {
    long numerator = Long.MAX_VALUE / 3 * 2;
    long denominator = Long.MAX_VALUE;

    int percentage = (int) (numerator / (denominator / 100));
    System.out.println("percentage = " + percentage);

  }
}

相反?也就是说,在除法之前,不要使分子变大,而要使分母变小。因为你知道分母是大的,所以除法不会给出0,这就是你不使用浮点数时通常写
(n*100)/d
的原因。

大家按照下面的方式实现,因为建议用BigDecimal和biginger进行计算。以下是实施:

    BigDecimal n = new BigDecimal(Long.MAX_VALUE);
    BigDecimal d = new BigDecimal(Long.MAX_VALUE);
    BigDecimal i = new BigDecimal(100);
    int percentage = n.multiply(i).divide(d).intValue();
    System.out.println(percentage);

为什么结尾的“+0.5”?我想这是为了更好的四舍五入…但是99.6将会是100,也许不是这样good@SteveMcLeod:是的,这与舍入有关(参见更新的答案)。我认为舍入到最接近的值是一个合理的默认值。@SteveMcLeod:当然,如果用例要求截断而不是舍入到最接近的值,那么可以安全地删除
+0.5
@SteveMcLeod-我认为这对于有整数并且知道它们很大的情况是正确的。通常的写作方式是为了应付小的情况而设计的。