You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么Java BigDecimal调用stripTrailingZeros后会输出科学计数法?

BigDecimal stripTrailingZeros后toString()输出科学计数法的原因及解决方案

现象复现

你遇到的输出差异是Java BigDecimal的标准行为,测试代码如下:

public static void main(String[] asd)
{
    // prints: "with stripTrailingZeros: 5E+1"
    System.out.println("with stripTrailingZeros: " + new BigDecimal("50").stripTrailingZeros());

    // prints: "without stripTrailingZeros: 50"
    System.out.println("without stripTrailingZeros: " + new BigDecimal("50").toString());
}

底层原因

这个行为是BigDecimal的两个设计规则共同导致的:

  • stripTrailingZeros的作用不止是删除末尾的零,还会同步调整BigDecimal的精度位(scale)和无标度值(unscaledValue):
    • 未调用方法的new BigDecimal("50")参数为:unscaledValue = 50,scale = 0
    • 调用stripTrailingZeros后参数变为:unscaledValue = 5,scale = -1
  • toString()方法的输出规则为:当scale为负数时,自动使用科学计数法输出,以保证输出的字符串长度最短,同时准确体现当前BigDecimal的精度状态。Java官方并没有保证toString()的输出是人类可读的普通数值格式,它的设计目标是能通过new BigDecimal(str)准确还原当前BigDecimal对象。

解决方案

针对JSON序列化返回值不一致的问题,全局配置Jackson的序列化规则是成本最低的通用方案,不存在不合理的问题,只需要几行代码就能全局生效,不需要对业务代码做任何修改:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JacksonConfiguration {
    @Bean
    public ObjectMapper customObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        // 全局启用BigDecimal输出为普通字符串,不使用科学计数法
        objectMapper.enable(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN);
        return objectMapper;
    }
}

如果只需要部分字段使用普通格式输出,不需要全局修改,可以在对应字段上添加序列化注解:

@JsonSerialize(using = ToStringSerializer.class)
private BigDecimal amount;

内容的提问来源于stack exchange,提问作者gshock

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 19:24:03