为什么乘以双精度时有不同的输出
本文关键字:输出 双精度 为什么 | 更新日期: 2023-09-27 18:32:08
假设我有以下内容:
double f;
double c = 5;
Console.WriteLine("{0} | {1}", c, f = 9 / 5 * c + 32);
这将给出输出:5 | 37
同时:
double f;
double c = 5;
Console.WriteLine("{0} | {1}", c, f = 9.0 / 5.0 * c + 32);
将给出正确的输出:5 | 41
(表示 5 摄氏度是多少华氏度)
我知道我正在与双倍工作,但我缺乏洞察力,为什么两种结果彼此不等同?
使用整数语法(9 而不是 9.0)时,每个操作都四舍五入,不带小数
因为 C 语言 [本质上] 被设计为一种与硬件无关的汇编语言。因此,除法,除非涉及浮点值是整数除法,否则CPU将在单个指令中完成。这意味着像这样的表达式:
int x = 9 ;
int y = 5 ;
int z = x / y ;
这通常会编译为单个机器指令(可能与其他机器指令一起将值加载/存储到寄存器/从寄存器加载/存储值,其最终结果是商和余数。因此,上述int z = x / y
将解析为 1
,将4
的其余部分留在表中(请注意,如果需要余数,请使用 %
运算符:int z = x % y
产生预期的4
。
如果其中一个操作数是浮点值,则使用浮点除法(从计算角度来说,成本很高)。
由于 C# 继承自该旧版,因此它的行为方式相同。因此,该标准的§14.7.2说
14.7.2 除法运算符
对于形式为
x / y
的操作,应用二进制运算符重载解析 (§14.2.4) 以选择特定的运算符实现。操作数将转换为参数类型 所选运算符,结果的类型是运算符的返回类型。下面列出了预定义的除法运算符。 运算符都计算
x
和y
的商。
整数除法:
int operator /( int x, int y ); uint operator /( uint x, uint y ); long operator /( long x, long y ); ulong operator /( ulong x, ulong y ); void operator /( long x, ulong y ); void operator /( ulong x, long y );
具有返回类型的运算符
void
始终生成编译时错误。因此 一个操作数的类型为long
,另一个操作数的类型为ulong
是错误的。如果右操作数的值为零,则抛出
System.DivideByZeroException
。除法将结果四舍五入为零,结果的绝对值为 小于 的商的绝对值的最大可能整数 两个操作数。当两个操作数具有相同的操作数时,结果为零或正数 当两个操作数具有相反的符号时,符号和零或负数。
如果左操作数是最小的
int
或long
值(−231 或 −263, 分别)并且右操作数–1
,则发生溢出。在checked
的背景下,这 导致抛出System.ArithmeticException
(或其子类)。在unchecked
上下文,它是实现定义的,即System.ArithmeticException
(或 其子类)被抛出或溢出未报告,结果值为 的左操作数。[省略浮点和小数除法的讨论]
这就是原因。