如何为两个不同的本地设置管理不同的 dcimal 分隔符?

问题描述

我有一台英语设置的笔记本电脑,我的同事有一台德国笔记本电脑。我有一个单元测试如下:

  @Test
  public void mytest() {
    String randomValue = roundFloat(4,0.32258437873357226);
    Assert.assertEquals(Double.parseDouble(randomValue),0.3225);
  }

  public String roundFloat(int decimalDigits,Number randomValue) {

    String formatPattern = getFormatPattern(decimalDigits);
    DecimalFormat decimalFormat = new DecimalFormat(formatPattern);
    decimalFormat.setRoundingMode(RoundingMode.FLOOR);
    return decimalFormat.format(randomValue);
  }

英语中的认十进制分隔符为 .,德语中为 ,。因此,该测试在我的机器上运行良好,但是当我的同事运行它时,它抱怨:

java.lang.NumberFormatException: For input string: "0,3225"
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2043)
    at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
    at java.lang.Double.parseDouble(Double.java:538)
    at de.vwag.fda.common.MeteringUnitTest.roundFloatTest(MeteringUnitTest.java:174)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:133)
    at org.testng.internal.TestInvoker.invokeMethod(TestInvoker.java:598)
    at org.testng.internal.TestInvoker.invokeTestMethod(TestInvoker.java:173)
    at org.testng.internal.MethodRunner.runInSequence(MethodRunner.java:46)
    at org.testng.internal.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:824)
    at org.testng.internal.TestInvoker.invokeTestMethods(TestInvoker.java:146)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:146)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:128)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at org.testng.TestRunner.privateRun(TestRunner.java:794)
    at org.testng.TestRunner.run(TestRunner.java:596)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:377)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:371)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:332)
    at org.testng.SuiteRunner.run(SuiteRunner.java:276)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:96)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1212)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1134)
    at org.testng.TestNG.runSuites(TestNG.java:1063)
    at org.testng.TestNG.run(TestNG.java:1031)
    at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:135)
    at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.executeMulti(TestNGDirectoryTestSuite.java:193)
    at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:94)
    at org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:146)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:377)
    at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:138)
    at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:465)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:451)

那么,我该如何修改我的测试,以便它针对所有可能的本地设置运行?

解决方法

来自the DecimalFormat documentation

To obtain a NumberFormat for a specific locale,including the default locale,call one of NumberFormat's factory methods,such as getInstance(). In general,do not call the DecimalFormat constructors directly,since the NumberFormat factory methods may return subclasses other than DecimalFormat.

这意味着您可以使用它来获取具有自定义语言环境的数字格式化程序,并像在代码中一样设置舍入模式:

NumberFormat format = NumberFormat.getNumberInstance(Locale.GERMAN);
if(format instanceof DecimalFormat) {
    ((DecimalFormat) format).setRoundingMode(RoundingMode.FLOOR);
}
,

我会在正确的语言环境中使用 System.printf

System.out.printf(Locale.GERMAN,"%.3f%n",123.723);
System.out.printf(Locale.ENGLISH,123.723);

印刷品

123,723
123.723

但格式化程序也接受语言环境。所以如果你想做货币,你可以打电话:

NumberFormat df = NumberFormat.getCurrencyInstance(Locale.ENGLISH);

您可以按如下方式四舍五入到指定的位数。

String randomValue = roundFloat(4,.32258437873357226,Locale.GERMAN);
System.out.println(randomValue);
randomValue = roundFloat(7,Locale.ENGLISH);
System.out.println(randomValue);

印刷品

0,3225
0.3225843

roundFloat 方法

public static String roundFloat(int decimalDigits,Double randomValue,Locale locale) {
    DecimalFormat df = (DecimalFormat)DecimalFormat.getInstance(locale);
    df.setMaximumFractionDigits(decimalDigits);
    df.setRoundingMode(RoundingMode.FLOOR);
   return df.format(randomValue);
}