不使用 SetRoundingMode() 截断浮点值

Posted

技术标签:

【中文标题】不使用 SetRoundingMode() 截断浮点值【英文标题】:Truncating a Float Value Without Using SetRoundingMode() 【发布时间】:2012-05-04 07:34:54 【问题描述】:

我在这里截断一个浮点数。但我的值正在四舍五入。我不想要那个。例如,如果我的值是 12.989 -> 它应该只打印为 12.98。有人可以帮忙吗 我不能使用十进制格式的 SetRoundingMode,因为它仅受 java 1.6 支持。 我的是 1.5 JDK。有人可以在不使用 SetRoundingMode() 方法的情况下帮助我吗????

        String pattern = "##,##0.00";        
        NumberFormat nf = NumberFormat.getNumberInstance();
        DecimalFormat df = (DecimalFormat)nf;      

        double fPart; 
        Float value=233.989f;
        String dstr = String.valueOf(value);
        dstr = dstr.substring(dstr.indexOf(".")+1);
        Long db = Long.valueOf(dstr);
        if(db > 0)
            df.applyPattern(pattern);
            System.out.println("input="+value+", fPart="+dstr);
                

        String output = df.format(value);

    System.out.println(output);

【问题讨论】:

【参考方案1】:

你总是可以使用老派的把戏,乘以 10^n,截断,除以 10^n:

float x = 233.989f;
x = (float)(Math.floor(x * 100) / 100);

我也尝试过 BigDecimal:

MathContext mc = new MathContext(5, RoundingMode.FLOOR)
BigDecimal decimal = new BigDecimal(233.989, mc);
System.out.println(decimal);

它可以完成这项工作,但您必须指定总位数。你不能只说我想要 2 位小数,我不在乎小数点后面的数字。这样MathContext的第一个参数是5,而不是2。如果你选择这种方法,你可以用Math.Ceil(Math.log10(x))快速计算非十进制数字。

注意:

除法(第一种方法)时,至少有一个操作数必须是浮点数(float 或 double) 在使用字符串(您编写代码)时,假定 '.' 是不安全的。是小数分隔符 使用 Math.floor 截断小数仅适用于正值

【讨论】:

如果您不知道数字是什么,但仍想实现该模式怎么办? “老派把戏”的失败率超过 90%。您不能将浮点值截断为特定的小数位数,因为它们没有要截断的小数位。 @Azfar:你的意思是你必须知道这些数字是什么意思?您始终可以为 MathContext 对象计算 setPrecision。我是否必须澄清如何做到这一点? @EJP:如果我们稍微改变常量,乘法和除法都将以双精度执行:Math.floor(x * 100.0) / 100。 AFAIK double 没有显示前 15 位数字的精度损失,我很漂亮,这对于 99% 的非科学微积分来说已经绰绰有余了。 @EmperorOrionii 当像 Math.floor(9.62 * 100 ) /100 这样的位数已经为 2 时,旧技巧不起作用,结果为 9.61【参考方案2】:

不确定我是否理解您的问题。但是如果你想截断而不向上或向下舍入,你可以使用就像 DecimalFormat df = new DecimalFormat("##.##"); df.format(12.912385);

【讨论】:

【参考方案3】:

您可以使用正则表达式来获取“.”之后的第二个数字。然后将字符串从开头减去该位置,然后将字符串转换为浮点数或双精度数。

Pattern pattern = Pattern.compile("regular expression");
Matcher matcher = pattern.matcher("your string");

if(matcher.find())

    int poz_begin = matcher.start();
    int poz_end = matcher.end();

【讨论】:

不是正则表达式。

以上是关于不使用 SetRoundingMode() 截断浮点值的主要内容,如果未能解决你的问题,请参考以下文章

将浮点数格式化为 NSString 时截断多余的零

在 X87 和 SSE FPU 中用户定义的点之后截断浮点数和双精度数

IEEE 754 二进制浮点数不精确

浮点数的精确值作为有理数

为啥 Amazon Redshift 会截断此 JSON 浮点数据的精度?

为啥C++里面浮点与整数相乘的结果跟在计算器里的不一样呢?浮点我选的float