手动格式化Java双

时间:2015-02-05 13:20:43

标签: java gwt

我想生成一个(非本地化的)字符串,表示一个双倍到'n'的小数位,最好是四舍五入。例如。到小数点后四位,1.234567 - > "1.2346"

我知道我可以使用BigDecimalDecimalFormatString.format()执行此操作,但在我的项目中,我受到约束,无法使用它们或任何第三方库。是否可以编写一个简单的函数来完成它?怎么样?

更新(更多细节):这个问题的原因是我想要一个在GWT和Java中使用相同代码的解决方案,并且需要最少量的代码和库。至关重要的是,格式化的数字不会根据浏览器的语言环境而改变(例如,当法国用户运行时,我不希望"1,2346"。)

在GWT中,我编写了这个Javascript包装函数:

/**
 * Convert a double to a string with a specified number of decimal places.
 * The reason we need this function is that by default GWT localizes
 * number formatting.
 *
 * @param d double value
 * @param decimalPlaces number of decimal places to include
 * @return non-localized string representation of {@code d}
 */
public static native String toFixed(double d, int decimalPlaces) /*-{
    return d.toFixed(decimalPlaces);
}-*/;

我想用一些简单的Java代替它,所以我可以在客户端和服务器上使用相同的代码。

public static String toFixed(double d, int decimalPlaces) {
    // TODO
}

2 个答案:

答案 0 :(得分:1)

由于您已加入GWT,如果您先致电NumberFormat.setForcedLatinDigits(true)强制使用拉丁数字和分隔符,则可以使用NumberFormat

如果您想要拉丁默认设置以外的特定区域设置,则必须创建一个扩展NumberFormat的类并覆盖getFormat以调用受保护的NumberFormat constructor并提供NumberConstants实施

答案 1 :(得分:0)

我写了以下功能。它在内部使用long因此无法使用某些非常大或非常小的double值,但这对我的用例来说还不错:

public static String toFixed(double d, int decimalPlaces) {
    if (decimalPlaces < 0 || decimalPlaces > 8) {
        throw new IllegalArgumentException("Unsupported number of "
                + "decimal places: " + decimalPlaces);
    }
    String s = "" + Math.round(d * Math.pow(10, decimalPlaces));
    int len = s.length();
    int decimalPosition = len - decimalPlaces;
    StringBuilder result = new StringBuilder();
    if (decimalPlaces == 0) {
        return s;
    } else if (decimalPosition > 0) {
        // Insert a dot in the right place
        result.append(s.substring(0, decimalPosition));
        result.append(".");
        result.append(s.substring(decimalPosition));
    } else {
        result.append("0.");
        // Insert leading zeroes into the decimal part
        while (decimalPosition++ < 0) {
            result.append("0");
        }
        result.append(s);
    }
    return result.toString();
}

试验:

@Test
public void formatsDoubleToSpecifiedNumberOfDecimalPlaces() {
    assertEquals("100.0000", toFixed(100d, 4));
    assertEquals("10.0000", toFixed(10d, 4));
    assertEquals("1.0000", toFixed(1d, 4));
    assertEquals("0.1000", toFixed(0.1d, 4));
    assertEquals("0.0100", toFixed(0.01d, 4));
    assertEquals("0.0010", toFixed(0.001d, 4));
    assertEquals("0.0001", toFixed(0.0001d, 4));
    assertEquals("0.0000", toFixed(0.00001d, 4));
    assertEquals("0.0000", toFixed(0.000001d, 4));

    assertEquals("12", toFixed(12.3456789d, 0));
    assertEquals("12.3", toFixed(12.3456789d, 1));
    assertEquals("12.35", toFixed(12.3456789d, 2));
    assertEquals("12.346", toFixed(12.3456789d, 3));
}

@Test
public void usesDotAsDecimalSeparatorRegardlessOfLocale() {
    Locale saved = Locale.getDefault();
    Locale.setDefault(Locale.FRANCE);
    try {
        assertEquals("123.4568", toFixed(123.456789d, 4));
    } finally {
        Locale.setDefault(saved);
    }
}

如果您可以对此进行改进,请发表评论或发布更好的答案。感谢。