在Java中确定数百万,亿,万亿,千万亿

时间:2014-06-26 15:29:10

标签: java

Standard dictionary numbers开始,我需要一种最快的方法来转换下面的数字:

1000000 = 1百万
1435234 = 1.43百万 350000000 = 3.5亿 1000000000 = 10亿 1765000000 = 1.76亿 1000000000000 = 1万亿 1345342345000 = 1.34万亿 1000000000000000 = 1万亿 100000000000000000 = 100万亿

并且进一步。

我试过以下这样的话:

public String truncateNumber(float floatNumber) {
    long million = 1000000L;
    long billion = 1000000000L;
    long trillion = 1000000000000L;
    long number = Math.round(floatNumber);
    if ((number >= million) && (number < billion)) {
        float fraction = calculateFraction(number, million);
        return Float.toString(fraction) + "M";
    } else if ((number >= billion) && (number < trillion)) {
        float fraction = calculateFraction(number, billion);
        return Float.toString(fraction) + "B";
    }
    return Long.toString(number);
}

public float calculateFraction(long number, long divisor) {
    long truncate = (number * 10L + (divisor / 2L)) / divisor;
    float fraction = (float) truncate * 0.10F;
    return fraction;
}

但我认为我的解决方案并不完全正确。那么,用Java做最快的方法是什么?非常感谢。

4 个答案:

答案 0 :(得分:4)

第一个问题是float没有足够的精度来表示这些数字。实际上,即使double对于Nonillion范围内的值也没有足够的精度 - 尽管这在这里可能不那么重要,因为你显然想要丢弃这个数字的大部分信息。

尽管如此,我已使用BigInteger在此处实现了它。如果您不关心精度问题,将其转换为使用double应该是直截了当的。

这里的基本思想是从1000的幂到相应的数字名称创建NavigableMap。可以使用floorEntry快速查找此地图,以找到最佳匹配功率(因此,数字名称)。

import java.math.BigInteger;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.TreeMap;

public class NumberNames
{
    public static void main(String[] args)
    {
        test("100", "Nearly nothing");
        test("1000", "1 Thousand");
        test("1230", "1.23 Thousand");
        test("1000000", "1 Million");
        test("1435234", "1.43 Million");
        test("350000000", "350 Million");
        test("1000000000", "1 Billion");
        test("1765000000", "1.76 Billion");
        test("1000000000000", "1 Trillion");
        test("1345342345000", "1.34 Trillion");
        test("1000000000000000", "1 Quadrillion");
        test("100000000000000000", "100 Quadrillion");
        test("1230000000000000000000000000000000000000000000000000000000000000", "1.23 Vigintillion");
    }

    private static void test(String numberString, String string)
    {
        BigInteger number = new BigInteger(numberString);
        System.out.println(number+" is "+createString(number)+" should be "+string);
    }



    private static final String NAMES[] = new String[]{
        "Thousand",
        "Million",
        "Billion",
        "Trillion",
        "Quadrillion",
        "Quintillion",
        "Sextillion",
        "Septillion",
        "Octillion",
        "Nonillion",
        "Decillion",
        "Undecillion",
        "Duodecillion",
        "Tredecillion",
        "Quattuordecillion",
        "Quindecillion",
        "Sexdecillion",
        "Septendecillion",
        "Octodecillion",
        "Novemdecillion",
        "Vigintillion",
    };
    private static final BigInteger THOUSAND = BigInteger.valueOf(1000);
    private static final NavigableMap<BigInteger, String> MAP;
    static
    {
        MAP = new TreeMap<BigInteger, String>();
        for (int i=0; i<NAMES.length; i++)
        {
            MAP.put(THOUSAND.pow(i+1), NAMES[i]);
        }
    }

    public static String createString(BigInteger number)
    {
        Entry<BigInteger, String> entry = MAP.floorEntry(number);
        if (entry == null)
        {
            return "Nearly nothing";
        }
        BigInteger key = entry.getKey();
        BigInteger d = key.divide(THOUSAND);
        BigInteger m = number.divide(d);
        float f = m.floatValue() / 1000.0f;
        float rounded = ((int)(f * 100.0))/100.0f;
        if (rounded % 1 == 0)
        {
            return ((int)rounded) + " "+entry.getValue();
        }
        return rounded+" "+entry.getValue();
    }
}

答案 1 :(得分:1)

我不会使用float,因为它没有太多精确度。请改用double。

static final long MILLION = 1000000L;
static final long BILLION = 1000000000L;
static final long TRILLION = 1000000000000L;

public static String truncateNumber(double x) {
    return x < MILLION ?  String.valueOf(x) :
           x < BILLION ?  x / MILLION + "M" :
           x < TRILLION ? x / BILLION + "B" : 
                          x / TRILLION + "T";
}

答案 2 :(得分:1)

我个人用这个。如果输入数字中需要小数,则可以使用BigDecimal。

BigInteger / BigDecimal优于Float或Double或Long,因为它可以保持更大的值。

 public static String customFormat(String pattern, BigInteger value) {
        //To force the output to be equal if the language is set to english, spanish, norwegian or japanese.
        NumberFormat nf = NumberFormat.getNumberInstance(Locale.ENGLISH);
        DecimalFormat df = (DecimalFormat)nf;
        df.applyPattern(pattern);
        String output = df.format(value);
        return output;


    }
    public static String numberConverter(BigInteger input) {
        String points = customFormat("###,###,###,###,###,###,###,###,###.###", input);
        String[] letters = new String[]{"Kc","Mc","Gc","Tc","Pc","Ec","Zc","Yc","Bc"};//your value names. Is not limited to two letters. Can also be more based on your maximum amount
        int size = points.length();
        String after = points;
        if (size > 3) {
            int firstPoint = points.indexOf(".");

            String re = points;
            re = points.substring(0,3);
            System.out.println(re);
            int pVar = 7;
            if(re.contains(",")){
                String[] parts = re.split(",");
                if(parts[0].length() == 2){
                    pVar = 6;
                }else if(parts[0].length() == 1){
                    pVar = 5;
                }
            }

            after = points.substring(0, pVar);
            int x = (size - firstPoint - 4/*3*/)/5;
            String bafter = after + " " + letters[x];//adds the value designation to the letter.
            after = bafter;
        }

        return after;
    }

我意识到由于它的长度,这不是最有效的代码,但它可以完美地运行。

1000以下的所有值都显示为其完整值。达到1000时,显示为1.000k。该代码旨在确保始终保持3个小数位。在if语句中将pvar设置向下更改为1(它始终将其设置为两位小数。)删除if语句将设置一个更大的动态数字,该数字会因max chars而变化。

有关BigINteger最大尺寸的一些技术信息。摘自this question

“没有理论限制.BigInteger类为它所要求的所有数据位分配所需的内存。

然而,有一些实际限制,由可用内存决定。还有进一步的技术限制,虽然你不太可能受到影响:有些方法假设这些位可以被int索引寻址,所以当你超过Integer.MAX_VALUE位时,事情就会开始中断。“

因此,如果您正在为计算机创建,请确保您有足够的内存用于那些大量的数据。

答案 3 :(得分:0)

简易Kotlin版本

    const val MILLION = 1000000L
    const val BILLION = 1000000000L
    const val TRILLION = 1000000000000L

    fun appendMillions(x: Long): String? {
        return when {
            x < MILLION -> x.toString()
            x < BILLION -> "${x.times(100).div(MILLION).times(0.01)}M"
            x < TRILLION -> "${x.times(100).div(BILLION).times(0.01)}B"
            else -> "${x.times(100).div(TRILLION).times(0.01)}T"
        }
    }