简体   繁体   English

如何将包含指数数字的字符串转换为十进制并返回到字符串

[英]How to convert a string containing an exponential number to decimal and back to string

I'm converting code between delphi and c#. 我在delphi和c#之间转换代码。
Values are stored as strings in a text file from the delphi app. 值作为字符串存储在delphi应用程序的文本文件中。 An example of the stored value is : '4.42615029219009E-5' 存储值的示例是:'4.42615029219009E-5'

Now in my c# app I need to read in that string value and then later have the capability to write out the value again. 现在在我的c#app中我需要读取该字符串值,然后才能再次写出该值。 Initially I used code similar to: 最初我使用的代码类似于:

string stringField = "4.42615029219009E-5";
double someMoneyVar = Convert.ToDouble(stringField)

later if I need to recreate the text file with the value of someMoneyVar then using a simple: 稍后如果我需要使用someMoneyVar的值重新创建文本文件,那么使用简单的:

string.Format("{0}", someMoneyVar)

would output: 输出:

4.42615029219009E-05 // note the 0

Lastly, I read that it is better to store money as decimals in c#. 最后,我读到最好将钱存入c#作为小数。 I've tried to convert the string value to a decimal using decimal.Parse(someMoneyVar, NumberStyles.Any) , however the formatting is lost. 我试图使用decimal.Parse(someMoneyVar, NumberStyles.Any)将字符串值转换为小数,但格式化将丢失。

I need the data to be output exactly as it was input. 我需要输出的数据与输入完全一致。

Note, the value of someMoneyVar may not always contain an exponential part. 注意,someMoneyVar的值可能并不总是包含指数部分。 eg 0.0428860331919443. 例如0.0428860331919443。 If there is no exponential part to the value of someMoneyVar then the value is written correctly to the text file. 如果someMoneyVar的值没有指数部分,则该值将正确写入文本文件。

Update: 更新:
Digging into delphi's FloatToStr function and help files (which is what stores the value in the text file) i came with the following: 深入研究delphi的FloatToStr函数和帮助文件(这是将值存储在文本文件中)我带有以下内容:

The resulting string uses fixed point format if the number of digits to the left of the decimal point in the value is less than or equal to the specified precision, and if the value is greater than or equal to 0.00001 (Edit: this should be 0.0001. There is an error in the delphi documentation) . 如果值中小数点左侧的位数小于或等于指定的精度,并且该值大于或等于0.00001,则结果字符串使用定点格式(编辑:此值应为0.0001 。delphi文档中有错误) Otherwise the resulting string uses scientific format, and the Digits parameter specifies the minimum number of digits in the exponent (between 0 and 4). 否则,结果字符串使用科学格式,Digits参数指定指数中的最小位数(0到4之间)。
... ...
If the section for positive values is empty, or if the entire format string is empty, the value is formatted using general floating-point formatting with 15 significant digits, corresponding to a call to FloatToStrF with the ffGeneral format . 如果正值部分为空,或者整个格式字符串为空,则使用具有15位有效数字的常规浮点格式对值进行格式化,对应于使用ffGeneral格式调用FloatToStrF General floating-point formatting is also used if the value has more than 18 digits to the left of the decimal point and the format string does not specify scientific notation. 如果值小数点左侧的值超过18位且格式字符串未指定科学记数法,也会使用常规浮点格式。

So bearing in mind that the FloatToStr function does a call to FloatToStrF uses 15 significant (precision) digits and a 0 as the minumum number of digits hence we end up with 因此,请记住FloatToStr函数调用FloatToStrF时使用15个有效(精确)数字和0作为最小数字位数,因此我们最终得到

4.42615029219009E-5 4.42615029219009E-5

if the digits was 2 then the number would be displayed as 如果数字是2则数字将显示为

4.42615029219009E-05 4.42615029219009E-05

According to the MSDN http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx#GFormatString 根据MSDN http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx#GFormatString
using the general format specifier, the precision of double is 15 and decimal is 29 使用通用格式说明符,double的精度为15,十进制为29

Fixed-point notation is used if the exponent that would result from expressing the number in scientific notation is greater than -5 and less than the precision specifier; 如果用科学记数法表示数字所得的指数大于-5且小于精度说明符,则使用定点表示法; otherwise, scientific notation is used. 否则,使用科学记数法。 The result contains a decimal point if required, and trailing zeros after the decimal point are omitted. 如果需要,结果包含小数点,并且省略小数点后的尾随零。 If the precision specifier is present and the number of significant digits in the result exceeds the specified precision, the excess trailing digits are removed by rounding. 如果存在精度说明符且结果中的有效位数超过指定的精度,则通过舍入删除多余的尾随数字。

However, if the number is a Decimal and the precision specifier is omitted, fixed-point notation is always used and trailing zeros are preserved. 但是,如果数字是十进制并且省略精度说明符,则始终使用定点表示法并保留尾随零。

If scientific notation is used, the exponent in the result is prefixed with "E" if the format specifier is "G", or "e" if the format specifier is "g". 如果使用科学记数法,如果格式说明符为“G”,则结果中的指数以“E”为前缀,如果格式说明符为“g”,则以“e”为前缀。 The exponent contains a minimum of two digits . 指数至少包含两位数 This differs from the format for scientific notation that is produced by the exponential format specifier, which includes a minimum of three digits in the exponent. 这与由指数格式说明符生成的科学计数法格式不同,指数格式说明符包含指数中至少三位数。

The result string is affected by the formatting information of the current NumberFormatInfo object. 结果字符串受当前NumberFormatInfo对象的格式设置信息的影响。 The following table lists the NumberFormatInfo properties that control the formatting of the result string. 下表列出了控制结果字符串格式的NumberFormatInfo属性。

One can easily set the precision eg mydecimal.toString("G15") however i still haven't found a way to set the number of digits after the 'E' sign as easily as in the delphi FloatToStrF function 可以轻松设置精度,例如mydecimal.toString(“G15”)但是我还没有找到一种方法来设置'E'符号后面的位数,就像delphi FloatToStrF函数一样容易

To convert strings to numbers, as you already figured out, you just use a double . 要将字符串转换为数字,正如您已经想到的那样,您只需使用double I'd try a different conversion though: 我会尝试不同的转换:

double myNum = double.Parse("<yournumber>", NumberStyles.AllowExponent | NumberStyles.Float, CultureInfo.InvariantCulture);

AllowExponent and Float should keep the notation, and InvariantCulture takes care of the decimal divider (which might not be a dot depending on the locale). AllowExponentFloat应该保留符号, InvariantCulture负责小数分隔符(根据语言环境可能不是一个点)。

You can output scientific notation numbers via string.Format() , like this: 您可以通过string.Format()输出科学记数字,如下所示:

double num = 1234.5678; // 1.2345678e+03
string.Format("{0:e}", num); // should output "1.2345678E+03"

If you have to distinguish between numbers with and without the "E+xx" part, you'll have to search for it before converting the string to double, and a full snippet (WARNING: not tested!) could look like: 如果您必须区分带有和不带“E + xx”部分的数字,您必须在将字符串转换为double之前搜索它,并且完整的片段(警告:未经测试!)可能如下所示:

string myString = ReadNumberFromFile(); // Just a placeholder method
double myNum = double.Parse(myString, NumberStyles.AllowExponent | NumberStyles.Float, CultureInfo.InvariantCulture);
string output = string.Empty; //this will be the "converted-back number" container
if (myString.IndexOf("e", StringComparison.OrdinalIgnoreCase) >= 0)
{
    //Number contains the exponent
    output = string.Format("{0:e}", num); // exponential notation 'xxxExx' casing of 'e' changes the casing of the 'e' in the string
}
else
{
    //TODO: Number does NOT contain the exponent
    output = string.Format("{0:f}", num); // fixed-point notation in the form 'xxxx.xxx'
}

The point here is that, as far as number go, being with or without an exponent doesn't make any difference whatsoever, it's just a matter of representation (and it makes little sense to distinguish between them: it's really the same thing ). 这里的要点是,就数字而言,无论没有指数都没有任何区别,它只是表示的问题(区分它们没有意义:它实际上是相同的事情 )。

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

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