手动格式化 Java double

Format a Java double by hand

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

我知道我可以使用 BigDecimalDecimalFormatString.format() 来做到这一点,但在我的项目中我受到限制,无法使用它们或任何第三方库.是否可以编写一个简单的函数来做到这一点?怎么样?

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

在 GWT 中,我写了这个 Java脚本包装函数:

/**
 * 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
}

我写了下面的函数。它在内部使用 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);
    }
}

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

由于您在 GWT 中,如果您先调用 NumberFormat.setForcedLatinDigits(true) 强制使用拉丁数字和分隔符,则可以使用 NumberFormat

如果你想要一个特定的语言环境而不是默认的拉丁语,你必须创建一个 class 来扩展 NumberFormat 并覆盖 getFormat 来调用受保护的 NumberFormat constructor and provide a NumberConstants 实施