简体   繁体   English

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

[英]Weird number conversion / encoding in Unity C#

I have this iOS project that embed an unity scene as a view.我有一个嵌入统一场景作为视图的 iOS 项目。 This problem occur on a device that set a localize that number has comma , as decimal seperator, rather than a point .此问题发生设置一个局部化该号码具有逗号的设备上,为十进制分隔符,而不是一个点.

I sent a parameter string from native code (swift) to unity.我从本机代码(swift)发送了一个参数字符串到 unity。 Unity then parse the string from iOS, make a new parameters to embed in another http request. Unity 然后解析来自 iOS 的字符串,创建一个新参数以嵌入另一个 http 请求。

this is the log in xcode:这是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}

I expected that I send 98.42519685039369, 100.06561679790026 , but for some reason, it becomes 9842519685039368.0, 10006561679790026.0 in the data request json string.我希望我发送98.42519685039369, 100.06561679790026 ,但由于某种原因,它在数据请求中变成了9842519685039368.0, 10006561679790026.0字符串。

How to fix this?如何解决这个问题? I have another log from a different device, with localize en-US and it seems the problem doesn't occur here.我有另一个来自不同设备的日志,使用 localize en-US,似乎这里没有出现问题。

The code in Unity (search for is_the_problem_here to jump right to the quetionable line: 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.
}

The other log:另一个日志:

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}

** UPDATE ** ** 更新 **

I've tried following this link but it's still not working as expect (same output as the first)我试过按照这个链接,但它仍然没有按预期工作(与第一个输出相同)

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

The 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();
    }
}

Sorry for being clueless.抱歉我一无所知。 What am I doing wrong here?我在这里做错了什么?

** UPDATE ** ** 更新 **

so changing Convert.toDouble() to double.Parse(ceiling, CultureInfo.InvariantCulture) fix the problem.因此将Convert.toDouble()更改为double.Parse(ceiling, CultureInfo.InvariantCulture)解决问题。 What weird issue.什么奇怪的问题。

Per default Convert.ToDouble(string) uses the language/region settings of the device the code is running on.默认Convert.ToDouble(string)使用运行代码的设备的语言/区域设置。

In some cultures the .在某些文化中, . character is not considered as the decimal splitter but rather the decimal group character.字符不被视为十进制分隔符,而是十进制组字符。

=> eg 1.000 is not one but rather one thousand! => 例如1.000不是一而是一千!


If dealing with string s across multiple devices you should always make sure to use the cultured overload Convert.ToDouble(string, IFormatProvider) and pass in the CultureInfo.InvariantCulture which is based on en-us .如果处理跨多个设备的string ,您应该始终确保使用文化重载Convert.ToDouble(string, IFormatProvider)并传入基于en-usCultureInfo.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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM