Unity C# 中的奇怪数字转换/编码

Weird number conversion / encoding in Unity C#

我有这个 iOS 项目,它嵌入了一个统一场景作为视图。 此问题发生在设置本地化的设备上,该数字具有逗号 , 作为小数点分隔符,而不是点 .

我从本机代码 (swift) 向 unity 发送了一个参数字符串。然后 Unity 解析来自 iOS 的字符串,创建一个新参数嵌入到另一个 http 请求中。

这是登录 xcode:

param from iOS: 615d48538edef900126a784e***616957b6f59835001137ae7b***98.42519685039369***100.06561679790026
Request Object:
- distanceFromCeiling: 9,84251968503937E+15
- distanceFromSideWall: 1,000656167979E+16
  - Obj: : UpdateRequest
  - Obj.distanceFromCeiling: : 9,84251968503937E+15
  - Obj.distanceFromSideWall: : 1,000656167979E+16
DATA request {"distanceFromCeiling":9842519685039368.0,"distanceFromSideWall":10006561679790026.0}

我预计我会发送 98.42519685039369, 100.06561679790026,但由于某种原因,它在数据请求 json 字符串中变成了 9842519685039368.0, 10006561679790026.0

如何解决这个问题?我有另一个来自不同设备的日志,使用 localize en-US,似乎这里没有出现问题。

Unity 中的代码(搜索 is_the_problem_here 直接跳转到有问题的行:

using System;
using System.Collections;
using System.Collections.Generic;
using Lean.Touch;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.UI;
using BestHTTP;
using System.Text;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using UnityEngine.UIElements;

public class GameManager : MonoBehaviour
{

// Other functions
// ====================================

void callApiFromIOS(string param)
{
    Debug.Log("param from iOS: " + param);

    string[] str = param.Split(new string[] { "***" }, StringSplitOptions.None);

    // is_the_problem_here
    System.Nullable <double> distanceFromCeiling = null;
    System.Nullable<double> distanceFromSideWall = null;

    if (str != null && str.Length >= 4)
    {
        string ceiling = str[2];
        if (!ceiling.Equals("null"))
        {
            // is_the_problem_here
            distanceFromCeiling = Convert.ToDouble(ceiling);
        }
       
        string sideWall = str[3];
        if (!sideWall.Equals("null"))
        {
            // is_the_problem_here
            distanceFromSideWall = Convert.ToDouble(sideWall);
        }
    }

    Debug.Log("Request Object: ");
    Debug.Log("- distanceFromCeiling: " + distanceFromCeiling);
    Debug.Log("- distanceFromSideWall: " + distanceFromSideWall);

    UpdateRequest updateRequest = new UpdateRequest(distanceFromCeiling, distanceFromSideWall);
    Debug.Log("  - Obj: : " + updateRequest);
    Debug.Log("  - Obj.distanceFromCeiling: : " + updateRequest.distanceFromCeiling);
    Debug.Log("  - Obj.distanceFromSideWall: : " + updateRequest.distanceFromSideWall);

    // is_the_problem_here
    string data = JsonConvert.SerializeObject(updateRequest);

    Debug.Log("DATA request " + data);

     // the rest of the code is set the json data as request body and send http.
}

其他日志:

param from iOS: 615d48538edef900126a784e***616957b6f59835001137ae7b***98.42519685039369***100.06561679790026

Request Object: 
- distanceFromCeiling: 98.4251968503937
- distanceFromSideWall: 100.0656167979
  - Obj: : UpdateRequest
  - Obj.distanceFromCeiling: : 98.4251968503937
  - Obj.distanceFromSideWall: : 100.0656167979
DATA request {"distanceFromCeiling":98.425196850393689,"distanceFromSideWall":100.06561679790026}

** 更新 **

我试过按照这个 link 但它仍然没有按预期工作(与第一个输出相同)

var converter = new FormattedDecimalConverter(CultureInfo.GetCultureInfo("en-US"));
string data = JsonConvert.SerializeObject(updateRequest, converter);

转换器class:

using System;
using System.Globalization;
using Newtonsoft.Json;

internal class FormattedDecimalConverter : JsonConverter
{
    private CultureInfo culture;

    public FormattedDecimalConverter(CultureInfo culture)
    {
        this.culture = culture;
    }

    public override bool CanConvert(Type objectType)
    {
        return true;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteValue(Convert.ToString(value, culture));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

抱歉无能为力。我在这里做错了什么?

** 更新 **

所以将 Convert.toDouble() 更改为 double.Parse(ceiling, CultureInfo.InvariantCulture) 解决了这个问题。什么奇怪的问题。

默认情况下 Convert.ToDouble(string) 使用设备的 language/region 设置代码 运行 打开。

在某些文化中,. 字符不被视为十进制分隔符,而是十进制组字符。

=> 例如1.000不是一而是一千!


如果在多个设备上处理 string,您应该始终确保使用基于 en-us.

的文化化重载 Convert.ToDouble(string, IFormatProvider) and pass in the CultureInfo.InvariantCulture
string ceiling = str[2];
if (!ceiling.Equals("null"))
{
    // is_the_problem_here
    distanceFromCeiling = Convert.ToDouble(ceiling, CultureInfo.InvariantCulture);
}
   
string sideWall = str[3];
if (!sideWall.Equals("null"))
{
    // is_the_problem_here
    distanceFromSideWall = Convert.ToDouble(sideWall, CultureInfo.InvariantCulture);
}