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

Angular与C#中大数带小数自动舍入问题求助

解决Angular接收高精度decimal值时的舍入问题

问题的核心原因是:JavaScript的Number类型仅能精确表示2^53以内的数值,你数据库中的100000000000000.165已经超出这个范围,当API以数字类型返回该值时,浏览器会自动将其转换为Number类型,导致精度丢失——这就是你在网络面板看到舍入的原因,即使Angular中使用BigNumber接收,传输阶段的精度损失已经发生。

解决方案步骤:

1. 修改C# API的DTO,将decimal属性序列化为字符串传输

这样可以避免浏览器自动转换为Number类型,保留完整精度。根据你使用的JSON序列化库选择对应实现:

方案一:使用System.Text.Json(.NET Core 3.0+默认)
  • 首先自定义一个decimal转字符串的转换器:
    using System.Globalization;
    using System.Text.Json;
    using System.Text.Json.Serialization;
    
    public class DecimalAsStringConverter : JsonConverter<decimal?>
    {
        public override decimal? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            if (reader.TokenType == JsonTokenType.String && decimal.TryParse(reader.GetString(), out var value))
            {
                return value;
            }
            return reader.TokenType == JsonTokenType.Null ? null : reader.GetDecimal();
        }
    
        public override void Write(Utf8JsonWriter writer, decimal? value, JsonSerializerOptions options)
        {
            if (value.HasValue)
            {
                writer.WriteStringValue(value.Value.ToString(CultureInfo.InvariantCulture));
            }
            else
            {
                writer.WriteNullValue();
            }
        }
    }
    
  • 给DTO的属性添加转换器特性:
    [JsonConverter(typeof(DecimalAsStringConverter))]
    public decimal? SctTotalPEO1 { get; set; }
    
方案二:使用Newtonsoft.Json(旧版本.NET常用)
  • 自定义转换器:
    using System.Globalization;
    using Newtonsoft.Json;
    
    public class StringDecimalConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(decimal) || objectType == typeof(decimal?);
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.Value is string str && decimal.TryParse(str, out var dec))
            {
                return dec;
            }
            return reader.Value;
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (value is decimal dec)
            {
                writer.WriteValue(dec.ToString(CultureInfo.InvariantCulture));
            }
            else if (value is decimal? nullableDec && nullableDec.HasValue)
            {
                writer.WriteValue(nullableDec.Value.ToString(CultureInfo.InvariantCulture));
            }
            else
            {
                writer.WriteNull();
            }
        }
    }
    
  • 给DTO属性添加特性:
    [JsonProperty(ConverterType = typeof(StringDecimalConverter))]
    public decimal? SctTotalPEO1 { get; set; }
    

2. Angular端处理字符串转BigNumber

此时API返回的SctTotalPEO1是字符串类型,你需要将其转换为BigNumber使用:

// 先在实体中定义为string类型(或直接在响应处理时转换)
export interface MyDto {
  sctTotalPEO1?: string;
}

// 接收响应后转换为BigNumber
import BigNumber from 'bignumber.js';

// 假设从API获取数据
this.http.get<MyDto>('/api/xxx').subscribe(data => {
  const preciseValue = data.sctTotalPEO1 ? new BigNumber(data.sctTotalPEO1) : null;
  // 使用preciseValue进行后续操作
});

验证效果

修改后,在Angular的网络面板中查看响应,SctTotalPEO1会以字符串形式显示"100000000000000.165",转换为BigNumber后即可保留完整精度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 22:33:18