C# Csharp-将单精度转换为十进制,而不转换为字符串

C# Csharp-将单精度转换为十进制,而不转换为字符串,c#,.net,decimal,C#,.net,Decimal,我从OdcDataReader中得到一个值,它是一个单一类型。我不希望使用单个in代码,因此我希望将其转换为十进制。然而,似乎每当我试图将其转换为小数点或其他任何形式时,它都会丢失几个小数点。我需要尽可能保持计算的准确性。我能找到的唯一方法是将单个字符串转换为带有“R”参数的字符串,然后将字符串解析为十进制。我创建了一些扩展方法来转换它们,但我希望有一种方法可以在不进行字符串转换和解析的情况下转换它们。记住,我需要保持精确性 Single sng = 1.32397970f; //

我从OdcDataReader中得到一个值,它是一个单一类型。我不希望使用单个in代码,因此我希望将其转换为十进制。然而,似乎每当我试图将其转换为小数点或其他任何形式时,它都会丢失几个小数点。我需要尽可能保持计算的准确性。我能找到的唯一方法是将单个字符串转换为带有“R”参数的字符串,然后将字符串解析为十进制。我创建了一些扩展方法来转换它们,但我希望有一种方法可以在不进行字符串转换和解析的情况下转换它们。记住,我需要保持精确性

Single sng = 1.32397970f;       // 1.32397974
decimal d = (decimal)sng;       // 1.32398M
d = Convert.ToDecimal(sng);     // 1.32398M
string xxx = sng.ToString("G"); // "1.32398"
xxx = sng.ToString("C");        // "$1.32"
xxx = sng.ToString("E");        // "1.323980E+000"
xxx = sng.ToString("e");        // "1.323980e+000"
xxx = sng.ToString("F");        // "1.32"
xxx = sng.ToString("G");        // "1.32398"
xxx = sng.ToString("N");        // "1.32"
xxx = sng.ToString("P");        // "132.40 %"
xxx = sng.ToString("R");        // "1.32397974" - Bingo!

// My extension methods
static class ExtensionMethods
{
    public static decimal ToDecimal(this Single value)
    {
        decimal d = decimal.Parse(value.ToString("R"));
        return d;
    }

    public static decimal ToDecimal(this Single? value, decimal dflt)
    {
        if (!value.HasValue)
            return dflt;

        decimal d = decimal.Parse(value.Value.ToString("R"));
        return d;
    }

    public static decimal? ToDecimal(this Single? value)
    {
        if (!value.HasValue)
            return null;

        decimal d = decimal.Parse(value.Value.ToString("R"));
        return d;
    }
}
decimal d = (decimal)Convert.ToDouble(sng);

先将其转换为双精度,然后再转换为十进制,这样可以获得更高的精度

Single sng = 1.32397970f;       // 1.32397974
decimal d = (decimal)sng;       // 1.32398M
d = Convert.ToDecimal(sng);     // 1.32398M
string xxx = sng.ToString("G"); // "1.32398"
xxx = sng.ToString("C");        // "$1.32"
xxx = sng.ToString("E");        // "1.323980E+000"
xxx = sng.ToString("e");        // "1.323980e+000"
xxx = sng.ToString("F");        // "1.32"
xxx = sng.ToString("G");        // "1.32398"
xxx = sng.ToString("N");        // "1.32"
xxx = sng.ToString("P");        // "132.40 %"
xxx = sng.ToString("R");        // "1.32397974" - Bingo!

// My extension methods
static class ExtensionMethods
{
    public static decimal ToDecimal(this Single value)
    {
        decimal d = decimal.Parse(value.ToString("R"));
        return d;
    }

    public static decimal ToDecimal(this Single? value, decimal dflt)
    {
        if (!value.HasValue)
            return dflt;

        decimal d = decimal.Parse(value.Value.ToString("R"));
        return d;
    }

    public static decimal? ToDecimal(this Single? value)
    {
        if (!value.HasValue)
            return null;

        decimal d = decimal.Parse(value.Value.ToString("R"));
        return d;
    }
}
decimal d = (decimal)Convert.ToDouble(sng);

不过,您将获得比一开始的单个值更高的精度。

将其转换为双精度,然后转换为十进制,您将获得更高的精度

Single sng = 1.32397970f;       // 1.32397974
decimal d = (decimal)sng;       // 1.32398M
d = Convert.ToDecimal(sng);     // 1.32398M
string xxx = sng.ToString("G"); // "1.32398"
xxx = sng.ToString("C");        // "$1.32"
xxx = sng.ToString("E");        // "1.323980E+000"
xxx = sng.ToString("e");        // "1.323980e+000"
xxx = sng.ToString("F");        // "1.32"
xxx = sng.ToString("G");        // "1.32398"
xxx = sng.ToString("N");        // "1.32"
xxx = sng.ToString("P");        // "132.40 %"
xxx = sng.ToString("R");        // "1.32397974" - Bingo!

// My extension methods
static class ExtensionMethods
{
    public static decimal ToDecimal(this Single value)
    {
        decimal d = decimal.Parse(value.ToString("R"));
        return d;
    }

    public static decimal ToDecimal(this Single? value, decimal dflt)
    {
        if (!value.HasValue)
            return dflt;

        decimal d = decimal.Parse(value.Value.ToString("R"));
        return d;
    }

    public static decimal? ToDecimal(this Single? value)
    {
        if (!value.HasValue)
            return null;

        decimal d = decimal.Parse(value.Value.ToString("R"));
        return d;
    }
}
decimal d = (decimal)Convert.ToDouble(sng);
但是,您将获得比单个值更高的精度。

您可以执行以下操作:

decimal d = Convert.ToDecimal((double)sng);
这将为您提供以下结果:

132397973537445

您可以执行以下操作:

decimal d = Convert.ToDecimal((double)sng);
这将为您提供以下结果:

132397973537445


我认为以下内容将满足您的标准,尽管我觉得使用单一货币表示货币值很奇怪。该方法已成功地基于有限测试对值进行了往返调整。该技术基于将有效位数的最大值限制为9,因为这是IEEE 754单精度二进制浮点值的最大值

Single sng = 1.32397970f;
Decimal dec = SingleToDecimal(sng);
Single sng2 = Convert.ToSingle(dec);
bool b = sng.Equals(sng2);  

我认为以下内容将满足您的标准,尽管我觉得使用单一货币表示货币值很奇怪。该方法已成功地基于有限测试对值进行了往返调整。该技术基于将有效位数的最大值限制为9,因为这是IEEE 754单精度二进制浮点值的最大值

Single sng = 1.32397970f;
Decimal dec = SingleToDecimal(sng);
Single sng2 = Convert.ToSingle(dec);
bool b = sng.Equals(sng2);  

你从一个单曲开始就失去了精确性。小数的精度实际上是双精度的两倍,所以是单精度的四倍。如果从一个单精度开始,你就会失去精度。小数的精度实际上是双精度的两倍,因此是单精度的四倍。我不认为我可以使用这个数字,它太精确了:1.32397973537445M。我希望能得到现在的号码。我不知道该绕多远。按现状使用它的最好方法是坚持单曲。无论如何,它比decimal快得多,因为它在大多数处理器上都有本机支持,而decimal类型没有。这是一个价格,当你做大量的乘法和除法时,doubles和singles不能很好地利用金钱。你会得到非常不可预测的结果,除非你不断地把它们包围起来。你试过把它四舍五入到你想要的精度吗?e、 g.`decimald=Math.RounddecimalConvert.ToDoublesng,7`如果我们有固定数量的价格,那将是理想的。不幸的是,它可以是任意数量的位,它是DB中的一个浮点值,所以除非我检查原始值,比如将其转换为字符串,并查看小数点左侧有多少个字符,否则我不知道转换后的值需要舍入多少位。至少我一时想不出办法。谢谢。我不认为我可以使用这个数字,它太精确了:1.32397973537445M。我希望能得到现在的号码。我不知道该绕多远。按现状使用它的最好方法是坚持单曲。无论如何,它比decimal快得多,因为它在大多数处理器上都有本机支持,而decimal类型没有。这是一个价格,当你做大量的乘法和除法时,doubles和singles不能很好地利用金钱。你会得到非常不可预测的结果,除非你不断地把它们包围起来。你试过把它四舍五入到你想要的精度吗?e、 g.`decimald=Math.RounddecimalConvert.ToDoublesng,7`如果我们有固定数量的价格,那将是理想的。不幸的是,它可以是任意数量的位,它是DB中的一个浮点值,所以除非我检查原始值,比如将其转换为字符串,并查看小数点左侧有多少个字符,否则我不知道转换后的值需要舍入多少位。至少我现在想不出一个办法。谢谢你,这是一个很好的答案,但由于太精确,我无法使用结果。我不知道这个数字会有多少个小数位,所以我不知道要舍入多少位。这是一个价格,因此可能会乘以一个非常大的数字,额外的精度将导致问题。谢谢,这是一个很好的答案,但由于精度太高,我将无法使用结果。我不知道这个数字会有多少个小数位,所以我不知道要舍入多少位。这是一个价格,梅也是
被一个非常大的数字乘以,额外的精度将导致问题。谢谢。是的,这很奇怪,但问题是我们的数据库是非常旧的Informix版本,运行在AIX机器上,我们使用Odbc驱动程序从运行.NET的windows机器访问它。OdbcDataReader在某一点上决定数据类型为单,即使Informix认为该字段是一个没有定义刻度的十进制字段。是的,这很奇怪,但问题是我们的数据库是非常旧的Informix版本,运行在AIX机器上,我们使用Odbc驱动程序从运行.NET的windows机器访问它。OdbcDataReader在某一点上决定数据类型为单,即使Informix认为该字段是一个没有定义刻度的十进制字段。