C# 将浮点转换为十进制,值错误

C# 将浮点转换为十进制,值错误,c#,floating-point,type-conversion,decimal,C#,Floating Point,Type Conversion,Decimal,我有一个浮点数:10071072872302,我需要把它转换成十进制 我得到的值是:1007107000000,这是错误的 如果我先将其转换为double,然后再将其转换为decimal: 我得到的值是:10071073357824,这也是错误的 如果我只是将float转换为double: 我得到的值是:10071073357824,这是错误的 我真的很困惑。我公司的数据库设计为十进制数据类型。我需要根据预先配置的公式以编程方式计算数据值,我需要使用返回浮点数据类型的NCalc库。不幸的是,我无

我有一个浮点数:10071072872302,我需要把它转换成十进制

我得到的值是:1007107000000,这是错误的

如果我先将其转换为double,然后再将其转换为decimal:

我得到的值是:10071073357824,这也是错误的

如果我只是将float转换为double:

我得到的值是:10071073357824,这是错误的

我真的很困惑。我公司的数据库设计为十进制数据类型。我需要根据预先配置的公式以编程方式计算数据值,我需要使用返回浮点数据类型的NCalc库。不幸的是,我无法将浮点转换为十进制

有谁能帮我解决这个僵局吗

编辑 我想澄清为什么我需要将浮点转换为十进制

要获得一个值,我需要计算如下表达式:ISA16+ISA8+ISNULLMAXABSBSMS10-ABSBSMS10,0,0

在获取数据库中的数据以替换表达式之后,我得到了如下表达式:10071072872302+872302+MAXABS-072872302-ABS2302,0

要计算此表达式的值,我使用NCalc库

表达有多种形式。但是,为了检查该值,我尝试使用10071072872302进行检查

我得到的结果是一个浮点值,因此我需要将其转换为十进制以匹配数据库中的数据类型。这就是我提出上述问题的原因

我有一个浮点数:10071072872302

浮点数=10071072872302f

不幸的是,这太晚了,float没有10071072872302的精确表示。所以最接近的机器编号是:10071073357824。这就是实际存储在变量中的值

例如,见:

您必须努力获得另一种表示形式,而不是浮点字符串、十进制或其他bigint库,才能获得此数字

请注意,对于这个精确的数字double number=10071072872302,double实际上应该是可以的,但在任何情况下,我都不会依赖浮点数类型float或double来存储精确的值

另请参见本一般问答:

我有一个浮点数:10071072872302

浮点数=10071072872302f

不幸的是,这太晚了,float没有10071072872302的精确表示。所以最接近的机器编号是:10071073357824。这就是实际存储在变量中的值

例如,见:

您必须努力获得另一种表示形式,而不是浮点字符串、十进制或其他bigint库,才能获得此数字

请注意,对于这个精确的数字double number=10071072872302,double实际上应该是可以的,但在任何情况下,我都不会依赖浮点数类型float或double来存储精确的值


另请参见此一般问答:

您在这里遇到了两个问题:

十进制与二进制。NCalc似乎正在使用浮点值计算表达式。但请注意,float和double是二进制浮点数类型,并且不是所有的十进制数都可以在二进制数类型中精确表示,而不管其长度如何;示例包括0.1和0.3。相比之下,decimal是一种十进制浮点数类型。如果NCalc正在将表达式中的十进制数解析为二进制数类型(如float或double),则存在舍入错误的风险,因为需要将某些十进制数转换为这些类型,即使表达式中的十进制数的位数相对较少。 有限精度。浮点、双精度和十进制是有限精度数字类型。例如,float的精度为24位,约为7位小数,decimal的精度约为28位小数。如果表达式中的数字位数超过了数字类型所能处理的位数,那么一旦转换为该类型,这些数字的精度就会降低。另一方面,BigInteger是一种精度实际上不受限制的数字类型,因此如果只处理整数,这可能是可行的。
我不熟悉NCalc,但是如果您关心的所有数字都有28位或更少的十进制数字,请查看是否可以将NCalc设置为解析和处理十进制数字类型中的数字。如果表达式中的所有数字都是整数,并且表达式中的任何内容都不会导致计算中出现分数,则如果NCalc支持,也可以使用BigInteger而不是decimal。如果NCalc不支持decimal或BigInteger,则可能需要使用另一个表达式解析库

您在这里遇到了两个问题:

十进制与二进制。NCalc似乎正在使用浮点值计算表达式。但请注意,float和double是二进制浮点数类型,并且不是所有的十进制数都可以在二进制数类型中精确表示,而不管其长度如何;示例包括0.1和0.3。相比之下,decimal是一种十进制浮点数类型。如果是NCalc 如果要将表达式中的十进制数解析为二进制数类型(如float或double),则存在舍入错误的风险,因为需要将某些十进制数转换为这些类型,即使表达式中的十进制数的位数相对较少。 有限精度。浮点、双精度和十进制是有限精度数字类型。例如,float的精度为24位,约为7位小数,decimal的精度约为28位小数。如果表达式中的数字位数超过了数字类型所能处理的位数,那么一旦转换为该类型,这些数字的精度就会降低。另一方面,BigInteger是一种精度实际上不受限制的数字类型,因此如果只处理整数,这可能是可行的。
我不熟悉NCalc,但是如果您关心的所有数字都有28位或更少的十进制数字,请查看是否可以将NCalc设置为解析和处理十进制数字类型中的数字。如果表达式中的所有数字都是整数,并且表达式中的任何内容都不会导致计算中出现分数,则如果NCalc支持,也可以使用BigInteger而不是decimal。如果NCalc不支持decimal或BigInteger,则可能需要使用另一个表达式解析库

我的问题已经解决了。我找到了Jint图书馆而不是NCalc


它就像一个符咒:

我的问题已经解决了。我找到了Jint图书馆而不是NCalc


它的工作原理就像一个符咒:

浮点类型最多可以存储7位精度。所以你得到的是正确的。考虑双或十进制。显然,您会倾向于后者,使用10071072872302m作为文本。10071072872302不能存储在浮点中而不丢失精度。number.ToStringF结果为1007107000000.00。实际上,我从第三方得到的浮点值是错误的,所以我需要转换成十进制。但这太难了,不管你从哪里得到的。该值不能放在浮点数内。通过转换无法恢复丢失的精度。浮点类型最多可存储7位精度。所以你得到的是正确的。考虑双或十进制。显然,您会倾向于后者,使用10071072872302m作为文本。10071072872302不能存储在浮点中而不丢失精度。number.ToStringF结果为1007107000000.00。实际上,我从第三方得到的浮点值是错误的,所以我需要转换成十进制。但这太难了,不管你从哪里得到的。该值不能放在浮点数内。您将无法通过转换来恢复丢失的精度。@MinhGiang好的,这更精确,谢谢您的编辑。我不知道NCalc,但是快速搜索显示有一个Convert.ToDecimal函数,你能尝试使用它而不是ToDouble吗?我得到的结果是一个浮点值:这是我对NCalc的知识的缺乏:你怎么知道它是一个float,就像System.float的别名一样?您的方法返回的签名是object,所以我不能确定引擎盖下到底发生了什么。@MinhGiang好的,这更准确,谢谢您的编辑。我不知道NCalc,但是快速搜索显示有一个Convert.ToDecimal函数,你能尝试使用它而不是ToDouble吗?我得到的结果是一个浮点值:这是我对NCalc的知识的缺乏:你怎么知道它是一个float,就像System.float的别名一样?你的方法返回的签名是object,所以我不能确定引擎盖下到底发生了什么。
float number = 10071072872302f;
var convertNumber = Convert.ToDecimal(number);
float number = 10071072872302f;
var convertNumber = Convert.ToDecimal(Convert.ToDouble(number));
float number = 10071072872302f;
var convertNumber = Convert.ToDouble(number);
private static object CalculateString(string formula)
    {
        var expression = new Expression(formula);

        expression.EvaluateFunction += (name, args) =>
        {
            switch (name)
            {
                case "ABS":
                    args.Result = Math.Abs(Convert.ToDouble(args.Parameters[0].Evaluate()));
                    break;
                case "MAX":
                    args.Result = Math.Max(Convert.ToDouble(args.Parameters[0].Evaluate()), Convert.ToDouble(args.Parameters[1].Evaluate()));
                    break;
            }
        };

        var value = expression.Evaluate();
        return value;
    }
var result = CalculateString("10071072872302");
static Engine engine = new Engine()
             .Execute("function ABS(number){return Math.abs(number);}")
             .Execute("function MAX(a,b){return Math.max(a,b);}")
             .Execute("function Max(a,b){return Math.max(a,b);}")
             .Execute("function ISNULL(a,b){return a==null?b:a;}")
             .Execute("function Divide(a,b){return a==null||b==null||b==0?null:a/b;}");

    private static object CalculateString(string formula)
    {
        var result = engine
            .Execute(formula)
            .GetCompletionValue()
            .ToObject();
        return result == null ? null : (object)Convert.ToDecimal(result);
    }