Avoid negative sign with compose() when output is zero, e.g. '-0' or '-0.0'

3 次查看(过去 30 天)
When compose outputs zero, it includes a negative sign if the number was negative, giving, e.g. -0 or -0.0. How can I avoid this? (Other than writing another function that does a string compare for every element output by compose and removes the negative sign if there are only zeros.)
num = -0.04;
compose('%.1f', num)
ans = 1x1 cell array
{'-0.0'}

采纳的回答

Stephen23
Stephen23 2025-2-20
num = -0.04;
txt = compose('%.1f', num)
txt = 1x1 cell array
{'-0.0'}
txt = regexprep(txt,'^-(0+(\.0+)?)$','$1')
txt = 1x1 cell array
{'0.0'}

更多回答(2 个)

dpb
dpb 2025-2-20
移动:dpb 2025-2-20
num = -0.04;
fprintf('%.1f\n', num)
-0.0
This is the normal and expected behavior when the value is rounded because it IS negative.
Changing it would be deceiving to the user who would then presume it was positive.
But, if one is adamant, then to post process just a string substitution is all that is required since the precision of the output is given, one doesn't have to do anything exotic.
  8 个评论
John D'Errico
John D'Errico 2025-2-20
编辑:John D'Errico 2025-2-20
No, you completely misunderstand me, but perhaps I could have said it differently.
It is a terribly bad idea for MATLAB to do something like that automatically in any way. Those negative numbers were generated by some process, some computation that apparently did something you do not like. That minus sign should be a flag to you that something happened, that there is something down there, NOT just a zero. I'm sorry though. Ignoring a problem, and pretending it does not exist is something serious.
Far better is to understand where they came from, and fix THAT. Fix the problem, rather than patching the symptom.
However, if you want to remove them anyway, without understanding why they happened, then that is YOUR choice to make. All you need do is essentially round those small values up to zero. And that is trivially done, with a simple test. You can write a function that checks for small negatives, and replaces them with zero, and you can do that without any string parsing. Your choice, and not at all difficult to do.
Leon
Leon 2025-2-21
编辑:Leon 2025-2-21
@John D'Errico, I say this with a calm tone: I don't know how you can make such strong statements without knowing anything about my data or experiments. Negative numbers are actually good in the specific context I was asking about, and I know exactly "why they happened". I'm not "ignoring a problem and pretending it doesn't exist", I just don't conisder it appropriate to use -0 in the tables I am generating, and -0 == 0 anyway.
I want to be clear that I'm not disagreeing with the default behaviour being the default behaviour; I understand that there are times when the sign would be of interest. However, I still disagree that it would be "a terribly bad idea" for there to be a parameter in Matlab to allow conversion of numbers to strings without having negative zeros. Having an optional parameter something like NoNegZero=true for compose() or a similar function would be useful in a variety of contexts and would have saved this whole discussion. You have your opinion, I have mine.
I was only asking if there was a better way to do it than writing my own function. Applying a tolerance before conversion is a fine solution and computationally faster than regexprep but I would need to parse the required precision from the formatSpec string if I wanted to be able to just create a replacement for the compose function that I'm using in various places; sometimes I want to output with different numbers of decimal places or significant figures. There is no problem though. Either rounding to a tolerance or regexprep after works fine, but I'm using the regexprep solution because it is a drop-in solution that requires less programming time & testing and I don't mind my code taking less than half a second extra to execute due to regexprep being slower than checking a tolerance and clamping to zero before.

请先登录,再进行评论。


Leon
Leon 2025-2-20
编辑:Leon 2025-2-20
Since it seems MATLAB doesn't have a function for this, here's the one I made. I also like Stephen23's idea of using a regular expression:
[Update: Sorry, my code here is clearly broken for more than one decimal place, as Stephen23 has pointed out below]
composezero('%.0f', [0.1 -0.1 0.01 -0.01 3 -3])
ans = 1x6 cell array
{'0'} {'0'} {'0'} {'0'} {'3'} {'-3'}
composezero('%.1f', [0.1 -0.1 0.01 -0.01 3 -3])
ans = 1x6 cell array
{'0.1'} {'0.1'} {'0.0'} {'0.0'} {'3.0'} {'-3.0'}
function c = composezero(formatSpec, A)
c = compose(formatSpec, A);
for ii = 1:numel(A)
val = A(ii);
str = c{ii};
if str(1) == '-' && round(val) == 0
c{ii} = str(2:end);
end
end
end
  3 个评论
Stephen23
Stephen23 2025-2-20
Note that the numeric rounding and the compiled text may diverge from each other, which leads to incorrect outputs for many values:
compose('%.2f', -0.025) % correct
ans = 1x1 cell array
{'-0.03'}
zerocompose('%.2f', -0.025) % wrong
ans = 1x1 cell array
{'0.03'}
function c = zerocompose(formatSpec, A)
c = compose(formatSpec, A);
for ii = 1:numel(A)
val = A(ii);
str = c{ii};
if str(1) == '-' && round(val) == 0
c{ii} = str(2:end);
end
end
end
Leon
Leon 2025-2-20
编辑:Leon 2025-2-20
@Stephen23, thanks for pointing this out. My code is actually wrong for anything more than one decimal place.
@Steven Lord, thanks. That's also a very nice solution, and should be much faster than regexp. What I like about Stephen23's regexp one is that it lets me make a drop-in replacement function, e.g.
function c = compose_u0(formatSpec, A)
c = compose(formatSpec, A);
c = regexprep(c, '^-(0+(\.0+)?)$', '$1');
end
rather than having to specify a tolerance each time, or have the function parse the formatSpec and work it out. This time I'm not having to process so many numbers that the regexp would slow things down noticeably.
And, as Steven23 said, perhaps there could be rounding-type issues, such as if I set the threshold at 0.5 or 0.05 (for nearest integer or one decimal place, respectively), there might be an edge case where compose outputs -0... but the value hadn't been changed to zero. (But maybe that can't happen under this circumstance; I don't know.)

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Environment and Settings 的更多信息

产品


版本

R2024a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by