是什么区别decimal,float并double在.NET?
什么时候会有人使用其中一种?
我知道浮点数具有精度,精度后的数字不可靠.
但是如果用于计算数字的等式是相同的呢?我可以假设结果也一样吗?
例如,我们有两个浮点数x和y.我们可以假设x/y机器1的结果与机器2的结果完全相同吗?IE ==比较将返回true
(int)((float)10.9 * 10)
Run Code Online (Sandbox Code Playgroud)
被评估为108.为什么?
IMO (int)-cast应在乘法后进行评估.
在添加可空浮动时,我注意到了一些非常奇怪的东西.请使用以下代码:
float? a = 2.1f;
float? b = 3.8f;
float? c = 0.2f;
float? result =
(a == null ? 0 : a)
+ (b == null ? 0 : b)
+ (c == null ? 0 : c);
float? result2 =
(a == null ? 0 : a.Value)
+ (b == null ? 0 : b.Value)
+ (c == null ? 0 : c.Value);
Run Code Online (Sandbox Code Playgroud)
result为6.099999而result2为6.1.我很幸运,有过一次,因为如果我改变值这个跌跌撞撞a,b和c行为通常显示正确.其他算术运算符或其他可空值类型也可能发生这种情况,但这是我能够重现的情况.我不明白的是,为什么隐式转换为float …
鉴于此示例C++代码段:
void floatSurprise()
{
// these come from some sort of calculation
int a = 18680, b = 3323524, c = 121;
float m = float(a) / c;
// variant 1: calculate result from single expression
float r1 = b - (2.0f * m * a) + (m * m * c);
cout << "r1 = " << r1 << endl;
// variant 2: break up the expression into intermediate parts,
/// then calculate
float
r2_p1 = 2.0f * m …Run Code Online (Sandbox Code Playgroud) 我正在C#/ .NET中开展科学计算和可视化项目,我们使用doubles来表示所有物理量.由于浮点数总是包含一些舍入,我们有简单的方法来进行相等比较,例如:
static double EPSILON = 1e-6;
bool ApproxEquals(double d1, double d2) {
return Math.Abs(d1 - d2) < EPSILON;
}
Run Code Online (Sandbox Code Playgroud)
很标准.
然而,EPSILON当我们遇到"相等"数量的误差大于我们预期的情况时,我们不断发现自己必须调整幅度.例如,如果将5个大doubles 相乘然后除以5次,则会失去很多精度.它已经达到了我们无法使EPSILON过大的程度,否则它会给我们带来误报,但我们仍然会得到假阴性.
一般来说,我们的方法是寻找更多数值稳定的算法来使用,但程序是非常计算的,而且我们已经能够做到这一点.
有没有人有任何好的策略来处理这个问题?我Decimal稍微调查了这个类型,但我对性能感到担心,我对它的了解并不知道它是否可以解决问题或者只是模糊它.Decimal如果它能解决这些问题,我愿意接受一个适度的性能命中(比方说,2x),但性能肯定是一个问题,因为代码主要受到浮点运算的限制,我不认为它是一个无理的担忧.我看到人们引用了100倍的差异,这肯定是不可接受的.
此外,切换到Decimal其他复杂情况,例如Math库中普遍缺乏支持,因此我们必须编写自己的平方根函数,例如.
有什么建议?
编辑:顺便说一句,我使用常数epsilon(而不是相对比较)的事实不是我的问题.我只是把它作为一个例子,它实际上不是我的代码的snippit.改变相对比较不会对问题产生影响,因为问题是由于数字变得非常大而后来又变小而失去精确度.例如,我可能有一个值1000,然后我对它进行一系列计算,这将导致完全相同的数字,但由于精度损失,我实际上有1001.如果我然后去比较这些数字,它不会如果我使用相对或绝对比较(只要我以对问题和规模有意义的方式定义比较),那就更重要了.
无论如何,正如Mitch Wheat建议的那样,算法的重新排序确实有助于解决这些问题.
我想知道哪种转换对于简单的数学运算更好(关于性能/速度和精度/最少损失)以及它们的不同之处是什么?
例:
double double1 = integer1 / (5 * integer2);
var double2 = integer1 / (5.0 * integer2);
var double3 = integer1 / (5D * integer2);
var double4 = (double) integer1 / (5 * integer2);
var double5 = integer1 / (double) (5 * integer2);
var double6 = integer1 / ((double) 5 * integer2);
var double7 = integer1 / (5 * (double) integer2);
var double8 = Convert.ToDouble(integer1 / (5 * integer2));
var double9 = integer1 / Convert.ToDouble(5 * integer2);
Run Code Online (Sandbox Code Playgroud)
实际上我的问题是关于转换而不是类型本身.
我有这个代码;
static int test = 100;
static int Test
{
get
{
return (int)(test * 0.01f);
}
}
Run Code Online (Sandbox Code Playgroud)
输出为:0
但是这段代码会有所不同
static int test = 100;
static int Test
{
get
{
var y = (test * 0.01f);
return (int)y;
}
}
Run Code Online (Sandbox Code Playgroud)
输出是:1
我也有这个代码
static int test = 100;
static int Test
{
get
{
return (int)(100 * 0.01f);
}
}
Run Code Online (Sandbox Code Playgroud)
输出是:1
我看一下IL输出,我不明白为什么C#在编译时执行这个数学运算并输出不同? 
这两个代码有什么区别?为什么我决定使用变量结果正在改变?
在许多编程语言中,像 0.1 + 0.2 这样的运算并不等于 0.3,而是 0.30000000000000004。因此,像 0.1+0.2 == 0.3 这样的检查将返回 false。
就我而言,这是由于 IEE 754 标准,这就是它在许多语言中很常见的原因。
在 C# 中也可以找到相同的行为。我使用下一个代码片段来测试它:
static void Main(string[] args)
{
double x = 0.2;
double y = 0.1;
double res = 0.3;
double z = x + y;
Console.WriteLine("bool result = {0}", z == res); // outputs false
Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)
但如果我使用相同的代码但使用浮点变量,一切都会以其他方式工作:
static void Main(string[] args)
{
float x = 0.2f;
float y = 0.1f;
float res = 0.3f;
float z = x + y;
Console.WriteLine("bool result …Run Code Online (Sandbox Code Playgroud) 我正在编写一个应用程序,我需要处理毫米和英寸.我写了一些简单的代码来缩放两个度量单位之间我也有一些代码来取一个十进制数并将其转换为分数.但是,当我使用Math.Floor从小数中分割整数时,我发现我并不总是得到返回的预期值.我附上了一些代码来证明这个问题.我希望最终的结果是6但我得到5.我很难理解为什么.有任何想法吗?
// This is a .Net 4.5 console application.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
double ValA = 6;
double ValB = 0;
double ValC = 0;
double ValD = 0;
ValB = ValA * 25.4;
ValC = ValB / 25.4;
ValD = Math.Floor(ValC);
Console.WriteLine(ValA.ToString());
Console.WriteLine(ValB.ToString());
Console.WriteLine(ValC.ToString()); // This returns 6 as expected
Console.WriteLine(ValD.ToString()); // But this returns 5.
Console.ReadKey();
}
}
}
Run Code Online (Sandbox Code Playgroud)