即使舍入结果为零,MATLAB似乎也记住了原始符号。由于小的负值被舍入为零,因此该信号不再有意义。
代码示例:
a = - 0.001;
ar = round(a,2);
fprintf('a: %.2f. a rounded: %.2f. Zero: %.2f\n', a,ar,0);
结果:
a:-0.00。四舍五入:-0.00。零:0.00
预期结果:
a:-0.00。圆形:0.00。零:0.00
答案 0 :(得分:3)
根据the post by Bob Gilmore (from The MathWorks) on the MATLAB forums,MATLAB在执行ANSI / IEEE浮点标准规定的各种操作时尊重符号位。
根据section 6.3的ANSI/IEEE Std. 754-1985,MATLAB表示符号位"即使操作数或结果为零或无限。"
因此,当使用round
时,即使所有指数和小数位都设置为0,sign bit仍然与输入相同(在您的情况下,这是1
表示负数)。 fprintf
还在显示您的值时会尊重此符号位,因此会添加显式负号。
您还可以通过明确指定您想要-0
:
fprintf('%0.2f\n', -0);
%// -0.00
这也可以用其他东西观察,例如除以0:
1/0 %// Inf
1/-0 %// -Inf
我们还可以通过将显示格式更改为hex
:
format hex
disp(0)
0000000000000000
disp(-0)
8000000000000000
注意第一个条目中的不同表示符号位的差异。
As @zeeMonkeez noted in the comments,一个简单的解决方法是在结果中添加0
,在-0的情况下,似乎会翻转符号位:
fprintf('%0.2f\n', -0 + 0);
%// 0.00
答案 1 :(得分:2)
这根本不是Matlab特有的。实际上,所有使用IEEE754进行浮点表示的程序都可能具有这种特殊性。
在IEEE-754格式中,有一个符号位。在舍入操作期间,该位可能保持不变。因此,即使结果最终是纯0
,符号位仍然存在。对于这种浮点数格式,这是完全正常的行为:
主要文章:签名零
在IEEE 754标准中,零已签名,这意味着存在 “正零”(+0)和“负零”(-0)。多数情况 运行时环境,正零通常打印为“0”和 负零为“-0”。这两个值在数值上表现相同 比较,但有些操作会为+0和+返回不同的结果 -0。例如,1 /( - 0)返回负无穷大,而1 / + 0返回 正无穷大(保持1 /(1 /±∞)=±∞的同一性)。 其他在x = 0处具有不连续性的常见函数可能会对待 对于任何负数y,+ 0和-0不同地包括log(x),signum(x)和y + xi的主平方根。和任何一样 近似方案,涉及“负零”的操作可以 偶尔会造成混乱。例如,在IEEE 754中,x = y不是 总是暗示1 / x = 1 / y,因为0 = -0但是1/0≠1 / -0。
来源:Wikipedia Floating_point Signed_zero
现在Matlab在零前面显示一个符号,因为你要求以浮点格式(%.2f
)显示它,所以Matlab尊重规范并显示符号。
如果让Matlab选择最佳的显示方式,Matlab将会很聪明并放弃零:
>> disp(ar)
0
此外,Matlab知道值为0
,如果您查询值的符号,则会返回正确的值:
>> sign(ar)
ans =
0
Matlab将返回-1
如果它被认为是负数,+1
如果它被认为是正数。所以尽管在显示时尊重IEEE-754规范,Matlab没有混淆,知道这个值没有任何有意义的符号。
总之,不要担心。它不会带来任何程序性问题或计算问题。
如果您唯一的悲痛是显示,另一种解决方法可能只是将绝对值乘以Matlab检测到的sign
(因为它检测到正确的符号)。
你可以制作一个自定义舍入函数,如果真的很重要的话可以处理它:
mround = @(x,n) abs(round(x,n))*sign(round(x,n)) ;
arm = mround(a,2) ;
fprintf('a: %.2f. a rounded: %.2f. Zero: %.2f\n', a,arm,0);
a: -0.00. a rounded: 0.00. Zero: 0.00
在此处,舍入操作被评估两次,因为我在内联函数中使用了它,但如果将其放在具有多行的函数中,则只评估舍入一次,然后使用相同的方法更正符号。