相关疑难解决方法(0)

什么时候应该使用double而不是decimal?

我可以说使用double(或float)代替以下三个优点decimal:

  1. 使用较少的内存.
  2. 更快,因为处理器本身支持浮点数学运算.
  3. 可以代表更大范围的数字.

但这些优势似乎只适用于计算密集型操作,例如建模软件中的操作.当然,在需要精确度时,不应使用双精度数,例如财务计算.那么有没有任何实际的理由选择double(或float)而不是decimal"正常"的应用程序?

编辑补充:感谢所有伟大的回应,我向他们学习.

还有一个问题:一些人认为双打可以更精确地代表实数.宣布时,我认为他们通常也会更准确地代表他们.但是,当执行浮点运算时,准确度是否会降低(有时是显着的)是真实的说法吗?

c# floating-point double types decimal

257
推荐指数
5
解决办法
5万
查看次数

在C#中将float转换为int时的奇怪行为

我有以下简单的代码:

int speed1 = (int)(6.2f * 10);
float tmp = 6.2f * 10;
int speed2 = (int)tmp;
Run Code Online (Sandbox Code Playgroud)

speed1和speed2应该具有相同的值,但事实上,我有:

speed1 = 61
speed2 = 62
Run Code Online (Sandbox Code Playgroud)

我知道我应该使用Math.Round而不是cast,但我想了解为什么值不同.

我查看了生成的字节码,但除了存储和加载外,操作码是相同的.

我也在java中尝试了相同的代码,我正确地获得了62和62.

有人可以解释一下吗?

编辑: 在实际代码中,它不是直接6.2f*10而是函数调用*常量.我有以下字节码:

速度1:

IL_01b3:  ldloc.s    V_8
IL_01b5:  callvirt   instance float32 myPackage.MyClass::getSpeed()
IL_01ba:  ldc.r4     10.
IL_01bf:  mul
IL_01c0:  conv.i4
IL_01c1:  stloc.s    V_9
Run Code Online (Sandbox Code Playgroud)

速度2:

IL_01c3:  ldloc.s    V_8
IL_01c5:  callvirt   instance float32 myPackage.MyClass::getSpeed()
IL_01ca:  ldc.r4     10.
IL_01cf:  mul
IL_01d0:  stloc.s    V_10
IL_01d2:  ldloc.s    V_10
IL_01d4:  conv.i4
IL_01d5:  stloc.s    V_11
Run Code Online (Sandbox Code Playgroud)

我们可以看到操作数是浮点数,唯一的区别是stloc/ldloc

至于虚拟机,我尝试使用Mono/Win7,Mono/MacOS和.NET/Windows,结果相同

c# floating-point int expression casting

127
推荐指数
3
解决办法
2万
查看次数

将结果转换为float方法返回float更改结果

为什么此代码False在.NET 4中打印?似乎一些意外的行为是由显式演员引起的.

我想要一个超越"浮动点不准确"或"不要那样做"的答案.

float a(float x, float y)
{
  return ( x * y );
}

float b(float x, float y)
{
  return (float)( x * y );
}

void Main()
{
  Console.WriteLine( a( 10f, 1f/10f ) == b( 10f, 1f/10f ) );
}
Run Code Online (Sandbox Code Playgroud)

PS:此代码来自单元测试,而不是发布代码.代码是故意以这种方式编写的.我怀疑它最终会失败,但我想知道确切的时间和原因.答案证明了这种技术的有效性,因为它提供的理解超出了对浮点确定性的通常理解.这就是用这种方式编写代码的重点; 刻意探索.

PPS:单元测试在.NET 3.5中传递,但现在在升级到.NET 4后失败了.

.net c# floating-point casting .net-4.0

53
推荐指数
1
解决办法
5133
查看次数

在.NET中强制浮点是确定性的吗?

我一直在阅读很多关于.NET中浮点确定性的内容,即确保具有相同输入的相同代码将在不同的机器上提供相同的结果.由于.NET缺少Java的fpstrict和MSVC的fp:strict等选项,因此似乎一致认为使用纯托管代码无法绕过这个问题.C#游戏AI Wars已经决定使用定点数学,但这是一个麻烦的解决方案.

主要问题似乎是CLR允许中间结果存在于FPU寄存器中,这些寄存器具有比类型的原始精度更高的精度,从而导致不可预测的更高精度结果.CLR工程师David Notario撰写MSDN文章解释了以下内容:

请注意,对于当前规范,它仍然是提供"可预测性"的语言选择.在每次FP操作之后,该语言可以插入conv.r4或conv.r8指令以获得"可预测的"行为. 显然,这非常昂贵,不同的语言有不同的妥协.例如,C#什么都不做,如果你想缩小,你必须手动插入(浮点)和(双)强制转换.

这表明,只需为每个表达式和计算浮点数的子表达式插入显式强制转换,就可以实现浮点确定性.有人可能会在float周围编写一个包装器类型来自动执行此任务.这将是一个简单而理想的解决方案!

然而,其他评论表明它并非如此简单.Eric Lippert最近表示(强调我的):

在某些版本的运行时中,显式转换为float会产生与不这样做不同的结果.当你明确地转换为float时,C#编译器会给运行时提供一个提示,说"如果碰巧使用这个优化,就把这个东西从超高精度模式中取出".

这对运行时的"提示"是什么?C#规范是否规定显式转换为float会导致在IL中插入conv.r4?CLR规范是否规定conv.r4指令会使值缩小到其原始大小?只有当这两者都成立时,我们才能依靠显式转换来提供浮点"可预测性",正如David Notario所解释的那样.

最后,即使我们确实能够将所有中间结果强制转换为类型的原生大小,这是否足以保证跨机器的可重复性,还是有其他因素如FPU/SSE运行时设置?

.net c# floating-point ieee-754

47
推荐指数
2
解决办法
4835
查看次数

浮点运算是否稳定?

我知道浮点数具有精度,精度后的数字不可靠.

但是如果用于计算数字的等式是相同的呢?我可以假设结果也一样吗?

例如,我们有两个浮点数xy.我们可以假设x/y机器1的结果与机器2的结果完全相同吗?IE ==比较将返回true

c# floating-point

37
推荐指数
4
解决办法
3157
查看次数

.NET Math.Log10()在不同的计算机上表现不同

我发现跑步了

Math.Log10(double.Epsilon) 
Run Code Online (Sandbox Code Playgroud)

-324在机器A上返回,但将-Infinity在机器B上返回.

他们最初的表现方式与回归相同-324.

两台机器都使用相同的操作系统(WinXP SP3)和.NET版本(3.5 SP1).机器B上可能有Windows更新,但是不知道发生了什么变化.

什么可以解释行为上的差异?

评论中讨论的更多细节:

  • 机器A CPU是32位Intel Core Duo T2500 2 GHz
  • 机器B CPU是32位Intel P4 2.4 GHz
  • 从使用多个第三方组件的大型应用程序中运行的代码收集的结果.但是,两台计算机上都运行相同的.exe和组件版本.
  • 打印Math.Log10(double.Epsilon)在机器B上打印一个简单的控制台应用程序-324,而不是-Infinity
  • 两台机器上的FPU控制字始终0x9001F(读取_controlfp()).

更新:最后一点(FPU控制字)不再成立:使用较新版本的_controlfp()显示不同的控制字,这解释了不一致的行为.(有关详细信息,请参阅下面的rsbarro答案.)

.net c# math epsilon

32
推荐指数
2
解决办法
2139
查看次数

浮点不准确性有多确定性?

我知道浮点计算存在准确性问题,并且有很多问题可以解释原因.我的问题是,如果我运行两次相同的计算,我是否可以始终依赖它来产生相同的结果?哪些因素可能会影响这个?

  • 计算之间的时间?
  • CPU的当前状态?
  • 不同的硬件?
  • 语言/平台/操作系统?
  • 太阳耀斑?

我有一个简单的物理模拟,并希望记录会话,以便他们可以重播.如果可以依赖计算,那么我只需要记录初始状态加上任何用户输入,我应该始终能够完全重现最终状态.如果计算不准确,那么在开始时错误可能会在模拟结束时产生巨大影响.

我目前在Silverlight工作,但有兴趣知道这个问题是否可以回答一般.

更新: 初始答案表明是,但显然这并不完全清楚,如所选答案的评论中所述.看起来我将不得不做一些测试,看看会发生什么.

c# math floating-point silverlight

25
推荐指数
3
解决办法
4167
查看次数

正弦值性能的计算与查找表?

假设您必须计算域在0.01到360.01之间的正弦(余弦或正切 - 无论如何).(使用C#)

什么会更高效?

  1. 使用Math.Sin
  2. 使用具有预先计算值的查找数组

我会反驳说,鉴于域名,选项2会快得多.在域精度(0.0000n)的什么时刻,计算的性能超过了查找.

c# math performance signal-processing

18
推荐指数
3
解决办法
1万
查看次数

Javascript中浮点数的精度可以成为非确定性的来源吗?

相同的数学运算可以在不同的架构或浏览器中返回不同的结果吗?

javascript math non-deterministic

13
推荐指数
2
解决办法
1352
查看次数

在Nullable Floats上添加时的好奇行为

在添加可空浮动时,我注意到了一些非常奇怪的东西.请使用以下代码:

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)

result6.099999result26.1.我很幸运,有过一次,因为如果我改变值这个跌跌撞撞a,bc行为通常显示正确.其他算术运算符或其他可空值类型也可能发生这种情况,但这是我能够重现的情况.我不明白的是,为什么隐式转换为float …

c#

12
推荐指数
1
解决办法
230
查看次数