How to change NaN string representation in C#?

邮差的信 提交于 2019-12-01 16:22:19

Double.ToString() uses NumberFormatInfo.CurrentInfo to format its numbers. This last property references to the CultureInfo that is currently set on the active thread. This defaults to the user's current locale. In this case its a Portuguese culture setting. To avoid this behavior, use the Double.ToString(IFormatProvider) overload. In this case you could use CultureInfo.InvariantCulture.

Additionally you can just switch the NaN symbol if you want to retain all other markup. By default globalization information is read only. Creating a clone will get around this.

System.Globalization.NumberFormatInfo numberFormatInfo = 
    (System.Globalization.NumberFormatInfo) System.Globalization.NumberFormatInfo.CurrentInfo.Clone();
numberFormatInfo.NaNSymbol = "NaN";

double num = double.NaN;
string numString = System.Number.FormatDouble(num, null, numberFormatInfo);

To set this on the current thread, create a copy of the current culture and set the number format info on the culture. Pre .NET 4.5 there's no way to set it for all threads. After creating each thread you would have to ensure a correct CultureInfo. As of .NET 4.5 there's CultureInfo.DefaultThreadCurrentCulture which defines the default culture for threads within the AppDomain. This setting is only considered when the culture of the thread has not been set yet (see MSDN).

Example for a single thread:

System.Globalization.CultureInfo myCulture =
     (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone();
myCulture.NumberFormat.NaNSymbol = "NaN";

System.Threading.Thread.CurrentThread.CurrentCulture = myCulture;   
string numString = double.NaN.ToString();

Simply don't pass NaN values to ToString.

For example (wrapping in an extension method for easy reuse):

static string ToCleanString(this double val)
{
    if (double.IsNan(val)) return "NaN";
    return val.ToString();
}

How about:

NumberFormatInfo myFormatInfo = NumberFormatInfo.InvariantInfo;

Point3D myPoint = new Point3D(1,1,double.NaN);
var pointString = myPoint.ToString(myFormatInfo);

First of all, the answer provided by Caramiriel is the solution to have double.NaN represented by ANY string you might desire.

Incidentally, I want the string "NaN", and here is what the docs say about NumberFormatInfo.NaNSymbol:

The string that represents the IEEE NaN (not a number) value. The default for InvariantInfo is "NaN".

Then I figured how to have my desired pure "NaN" string AND get rid of the comma separator, by using the default provided by InvariantCultureInfo, adding the folloing line just after the current thread is created:

Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;

And that worked fine!

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!