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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10415531/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 00:57:39  来源:igfitidea点击:

Overflow-safe way to calculate percentage from two longs in Java

java

提问by Steve McLeod

I have two non-negative longs. They may be large, close to Long.MAX_VALUE. I want to calculate a percentage from the two numbers.

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

Usually I'd do this:

通常我会这样做:

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

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

This is not correct if numerator is within two order of magnitudes to Long.MAX_VALUE.

如果分子在 Long.MAX_VALUE 的两个数量级内,则这是不正确的。

What's a correct, simple, and fast way to do this?

什么是正确、简单和快速的方法来做到这一点?

回答by NPE

I'd use:

我会用:

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

The 100.0forces floating-point math from that point on, and the + 0.5rounds to the nearest integer instead of truncating.

100.0部队从该点浮点数学运算,并+ 0.5四舍五入为最接近的整数,而不是截断。

回答by esej

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

If you divide a longwith a longyou will get a long, that is not good for percentages.

如果您将 along与 a相除,long您将得到 a long,这对百分比不利。

回答by Oliver Charlesworth

The trivial way is to convert both to floator doublebefore doing the calculation, at the expense of a slight loss in precision. It's also slow, in comparison to alternatives.

简单的方法是在计算之前floatdouble之前进行转换,代价是精度略有下降。与替代品相比,它也很慢。

One alternative is to split each value into two 32-bit components, and do long-multiplication and long-division.

一种替代方法是将每个值拆分为两个 32 位分量,并进行长乘法和长除法。

回答by Flexo

Unless I'm missing something obvious can't you just write:

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

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);

  }
}

instead? I.e. Instead of making the numerator bigger before division make the denominator smaller. Since you know the denominator is large there's no risk that the division will give 0, which is the reason for usually writing (n * 100) / dwhen you're not using floating point numbers.

反而?即不是在除法之前使分子变大,而是使分母变小。由于您知道分母很大,因此除法不会产生 0 的风险,这就是通常(n * 100) / d在您不使用浮点数时编写的原因。

回答by Leninkumar Koppoju

Guys implement in following way because it is suggested to do calculations with BigDecimal and BigInteger. Here is implementation:

伙计们按照以下方式实现,因为建议使用 BigDecimal 和 BigInteger 进行计算。这是实现:

    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);