相同的小数如何具有不同的位,并且ToString()的格式不同?

时间:2012-08-09 16:12:52

标签: c# .net oracle odp.net

在我们的Oracle数据库中,我有一个表(比如MYTABLE),其列VALUE_NUMBER类型为NUMBER(NULL,未指定精度)。此表包含值1178.2

使用标准ADO.Net(实际上是ODP.Net)从此列检索数据,然后将十进制值转换为字符串时,我得到'1178.20'。显然,在将常量1178.2M转换为字符串时,输出为1178.2

深入挖掘,我查看了十进制.GetBits()的输出,结果证明是不同的,尽管在比较两个数字时它们实际上被认为是相等的。

下面的代码示例说明了行为:

using (var connection = new OracleConnection("my connection string"))
{
    connection.Open();
    var command = connection.CreateCommand();
    command.CommandText = "SELECT VALUE_NUMBER FROM MYTABLE";
    command.CommandType = CommandType.Text;
    using (command)
    {
        var reader = command.ExecuteReader(CommandBehavior.Default);
        reader.Read();
        decimal oracleDecimal = reader.GetDecimal(reader.GetOrdinal("VALUE_NUMBER"));
        Console.WriteLine(oracleDecimal); // output: 1178.20 (NOT expected)
        var bitsFromOracle = decimal.GetBits(oracleDecimal).Select(x => x.ToString());
        var bitsFromOracleString = string.Join(",", bitsFromOracle.ToArray());
        Console.WriteLine(bitsFromOracleString); // 117820,0,0,131072

        // sanity check
        const decimal constantDecimal = 1178.2M;
        Console.WriteLine(constantDecimal); // output: 1178.2 (expected)
        var bitsFromConstant = decimal.GetBits(constantDecimal).Select(x => x.ToString());
        var bitsFromConstantString = string.Join(",", bitsFromConstant.ToArray());
        Console.WriteLine(bitsFromConstantString); // 11782,0,0,65536

        Console.WriteLine(oracleDecimal == constantDecimal); // True 
    }
}

应如何解释?

这是CREATE&表格。 INSERT脚本使这项工作:

CREATE TABLE MYTABLE (
  ID  NUMBER(10)             NOT NULL,
  VALUE_NUMBER           NUMBER
);

INSERT INTO MYTABLE(ID,VALUE_NUMBER) VALUES(1,1178.2);

更新:

@Vash及其后续评论的回答得出了正确的结论,即.Net十进制类型实际上包含有关它的位数的信息,即使它们与相等无关。 1178.2M1178.20M因此而具有不同的位表示,但显然.Equals()方法和==运算符认为这些数字相等。

3 个答案:

答案 0 :(得分:1)

您遇到的主要问题是您没有将任何格式应用于从数据库中收到的行数据。

如果你想要特定的格式,你应该指定它。在文档中,您将找到Formatting Types,其中包含有关如何处理格式设置的所有信息。

如果您只想获得结果

Console.WriteLine(valueNumber.ToString("N1", CultureInfo.InvariantCulture));

答案 1 :(得分:0)

这会导致显示问题或计算问题吗?

如果您只想根据需要显示输出,可以使用valueNumber.ToString("G")吗?

答案 2 :(得分:-1)

你做不到。如果你想这样做,你将不得不将它转换为String。

select 1123.80 num from dual;

select to_char(1123.80, 9999.99) from dual;

即。唯一的方法是

SQL> INSERT INTO MYTABLE(ID,VALUE_NUMBER) VALUES(1,1178.20);
SQL> SELECT to_char(VALUE_NUMBER, 9999.99) NUM FROM MYTABLE

NUM
-------------------
1178.20 (string/varchar)

SQL> SELECT VALUE_NUMBER NUM FROM MYTABLE

NUM
-------------------
1178.2 (number)

这可能会导致在稍后对该值执行数字(十进制)操作时出现问题,因为它变为string并且需要再次转换/转换为number,这不是一种非常推荐的方法。即使您将精度从NUMBER(10,2)转移到NUMBER(10),结果也会相同。