【问题标题】:How do I covert the decimal places of a double to a string? [duplicate]如何将双精度数的小数位转换为字符串? [复制]
【发布时间】:2020-05-08 02:41:13
【问题描述】:

我有 4 个例子:

double a = 1.05;
double b = 0.000056;
double c = 0.7812;
double d = 1.2;

我要做的是首先找到有多少个位置值。 在这种情况下

int inta = 2;
int intb = 6;
int intc = 4;
int intd = 1;

然后我想创建一个字符串,其中“0”代表这些数字。这是一个 ToString()

string stra = ".00";
string strb = ".000000";
string strc = ".0000";
string strd = ".0";

所以我唯一的东西就是一个双倍。我需要位置值,然后是如何创建字符串。

【问题讨论】:

  • 如何:将数字转换为长度很长的字符串(如 10 个小数位)。然后删除所有前导数字(直到点)。然后删除所有尾随零。
  • @Flydog57 问题在于不同的值a != b 可以具有相同的字符串表示,例如below,即使您查看 17 位(这是可靠有效的最大数量)也会发生这种情况double 类型的数字。
  • 我在标题中读到了“十进制”,并在我的脑海中出现了decimal。是的,double 无法使用

标签: c# string math int double


【解决方案1】:

您可以将双精度转换为字符串,然后获取子字符串:

double a = 1.05;

// Convert to string
string aString = a.ToString();

// Get substring
string result = aString.Substring(aString.LastIndexOf('.'));

// Get number of decimals
int numDecimals = result.Length - 1;

// Create string based on decimal count
string zeroString = ".";
for (int i = 0; i < numDecimals; i++) {
   zeroString += "0";
}

Console.WriteLine(result);
Console.WriteLine(numDecimals);
Console.WriteLine(zeroString);
// .05
// 2
// .00

** 确保这适用于所有文化,而不仅仅是那些使用“.”的文化。作为小数点分隔符,您可以替换:

LastIndexOf('.')

LastIndexOf(System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.CurrencyDecimalSeparator)

(感谢@John)

【讨论】:

  • 这不适用于所有文化!
  • 谢谢,这很有帮助。那么如何使用“.00”创建一个新字符串?
  • @jason.kaisersmith ,不,不会。但是从这个问题来看,我认为他的代码只会在包含“。”的文化下运行。为小数。我已编辑答案以包含警告
  • 当不使用System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.CurrencyDecimalSeparatorSytem.Globalization.CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator时,而不是对其进行硬编码?
  • @lakersfan 我已更新答案以包含“.00”字符串
【解决方案2】:

双精度数并不能准确地表示所有以 10 为底的分数。相反,您应该使用小数类型。

decimal a = 1.05;
decimal b = 0.000056;
decimal c = 0.7812;
decimal d = 1.2;
decimal e = 1.456000;

a.ToString() == "1.05"
b.ToString() == "0.000056"
c.ToString() == "0.7812"
d.ToString() == "1.2"
e.ToString() == "1.456000"

public static decimal Normalise(this decimal value) => value / 1.000000000000000000000000000000000m;

e.Normalise().ToString() == "1.456"

【讨论】:

  • 对。例如,(双)0.1m == 3602879701896397 / 36028797018963968。
  • 关于双精度与小数的观点可能是准确的,但这并不能回答问题。应该是评论。
  • @Herohtar 碰巧我刚刚发布了另一个(非)答案,我认为对于所述问题不存在“正确”答案。
【解决方案3】:

我认为问题不成立。具体来说,这部分:

首先找出有多少[十进制]位值

小数位数是一个表示问题,而不是数字的固有属性。在写入double a = 0.3; 时,存储到变量a 中的是最接近精确十进制0.3 的双精度值。该值接近 0.3,但与 0.3 不同,因为 IEEE-754 是基于二进制的,0.3 是非终止二进制分数。但是,一旦分配,变量a 就无法记住它的来源,或者源代码是否将其作为double a = 0.3;double a = 0.29999999999999999;

考虑以下 sn-p:

double a = 0.3;
double b = 0.2999999999999999;
double c = 0.29999999999999999;
Console.WriteLine("a = {0}, b = {1}, c = {2}, a==b = {3}, b==c = {4}, a==c = {5}", a, b, c, a==b, b==c, a==c);

输出是:

a = 0.3, b = 0.3, c = 0.3, a==b = False, b==c = False, a==c = True

这表明变量ac 比较相等,即它们保持精确相同的值,但一个定义为1 个十进制数字,而另一个定义为17 个十进制数字。重点是说与浮点相关的小数位数是没有意义的,因为正如这个例子所示,相同的值可以有不同的小数位数的不同表示。 .

作为旁注,上面还表明bc 是不同的值,尽管它们仅在小数点后第 17 位不同。这与具有between 15 and 17 有效十进制数字的double 类型一致,这就是为什么第16 位和第17 位一般不能忽略的原因。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    相关资源
    最近更新 更多