octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Preserving signbit for range operator


From: Rik
Subject: Re: Preserving signbit for range operator
Date: Wed, 27 Feb 2013 17:39:02 -0800

On 02/27/2013 05:16 PM, Daniel J Sebald wrote:
> On 02/25/2013 04:17 PM, Daniel J Sebald wrote:
>> On 02/25/2013 03:57 PM, Michael D. Godfrey wrote:
>>> On 02/25/2013 04:11 PM, Daniel J Sebald wrote:
>>>> octave:28> [-0:3:5]
>>>> ans =
>>>>
>>>> 0 3
>>>>
>>>> which is not abiding by the definition.
>>> But, this is what Matlab gets.
>>
>> Does -0 by itself produce -0 or 0? If the former, then Matlab isn't
>> abiding by its definition. If the latter, then somehow -0 has to be
>> input for some variable to test.
>
> Any progress or insight on this?
>
> At this point, I think the issue here is the manner in which value is
> treated and displayed.  That is, Matlab may preserve the sign bit in
> computations, but when it displays an integer (as opposed to float) there
> is no -0.  -0 is mapped to 0 before being used in print or display
> operations.
>
> To illustrate, here are some results from Octave using the sprintf command:
>
> octave:25> sprintf("%d ",[-0])
> ans = 0
> octave:26> sprintf("%f ",[-0])
> ans = -0.000000
>
> From this I conclude the negative sign is preserved but lost when the
> output format is an integer.  I say it is lost because of the following
> result:
>
> octave:28> sprintf("%+d ",[-0])
> ans = +0
> octave:29> sprintf("%+f ",[-0])
> ans = -0.000000
>
This is correct behavior.  The IEEE floating point format for a number has
a signbit, mantissa, and exponent.  Therefore it is possible to have a
mantissa of 0 and flipping the signbit will give -/+ 0.  The '%d' format
argument asks for a conversion of a floating point value to an integer. 
Integers are generally stored using two's complement format for which there
is only a single 0 and it is +0.  Thus '+0' is the integer representation
of the floating point number '-0'.
> OK, so now let's first address what Octave is doing INTERNALLY.  I'm
> going to try and take the display element out of this and just answer
> what the result should be for ranges, and I think there might be a mistake.
>
> octave:42> sprintf("%+f ",[0:3:6])
> ans = +0.000000 +3.000000 +6.000000
> octave:43> sprintf("%+f ",[0:-3:-6])
> ans = +0.000000 -3.000000 -6.000000
> octave:44> sprintf("%+f ",[-0:3:6])
> ans = +0.000000 +3.000000 +6.000000    ## INCORRECT
> octave:45> sprintf("%+f ",[-0:-3:-6])
> ans = -0.000000 -3.000000 -6.000000
> octave:46> sprintf("%+f ",[6:-3:0])
> ans = +6.000000 +3.000000 +0.000000
> octave:47> sprintf("%+f ",[6:-3:-0])
> ans = +6.000000 +3.000000 +0.000000
> octave:48> sprintf("%+f ",[-6:3:0])
> ans = -6.000000 -3.000000 +0.000000
> octave:49> sprintf("%+f ",[-6:3:-0])
> ans = -6.000000 -3.000000 +0.000000
>
> There is one case which I think is internally incorrect.  Going by the
> algorithm definition, [a:z:b] should have as its first element 'a' unless
> the range is nonsensical in which case the empty set results. Therefore,
> the ## above should have -0.000000 as the first element.  The last
> element of [a:z:b] is not necessarily 'b', it is whatever the computation
> turns out to be, e.g., 6 + 2 * -3  which is 0, not -0.
I agree with you.  Unless it is a null range, the first element should be a
direct copy of the base value of the range including the signbit.

>
> Now, let's address the DISPLAY aspect of this by removing the sprintf(),
> which presumably will treat the values as integers.  Again, there looks
> to be an answer that is incorrect (in a display perspective):
>
> octave:53> [0:3:6]
> ans =
>
>    0   3   6
>
> octave:54> [0:-3:-6]
> ans =
>
>    0  -3  -6
>
> octave:55> [-0:3:6]
> ans =
>
>    0   3   6
>
> octave:56> [-0:-3:-6]
> ans =
>
>   -0  -3  -6              *** INCORRECT
>
> octave:57> [6:-3:0]
> ans =
>
>    6   3   0
>
> octave:58> [6:-3:-0]
> ans =
>
>    6   3   0
>
> octave:59> [-6:3:0]
> ans =
>
>   -6  -3   0
>
> octave:60> [-6:3:-0]
> ans =
>
>   -6  -3   0
>
> I'm now thinking, as Michael points out, that all the results above
> should have 0 and no -0, even though internally the -0 should be retained
> in the proper case.
>
> Notice that the *** above is the same scenario as the incorrect result ##
> internally.  Rik, could you please think this over and check the
> pertinent case in the code for that scenario?  Perhaps there is a bug. Or
> if you agree there is a bug, then go ahead and file a bug report.
I think this is an inconsistency, although I'm not sure if we want to fix it.

The display routine makes a guess at whether something is an integer, even
if it happens to be stored in a floating point format.

For example, the following shows how Octave displays a floating point
number which exceeds the current precision.

x = [0 2 4.0000001]
x =

   0.00000   2.00000   4.00000

You can tell that these are not integers, even though they appear to be,
because Octave has put in the decimal point and is showing extra zeros of
precision.

By contrast, true integers don't have any decimal portion and can be
identified by their lack of a decimal point

x = [0 2 4]
x =

   0   2   4

I will have to check, but I don't think we are using the integer format
code '%d' when we print integers.  Instead, I think we are printing them as
floats with the width of the decimal portion set to zero.

For example,
x = [-0 2 4];
sprintf ("%4.0f ", x)
ans =   -0    2    4

--Rik


reply via email to

[Prev in Thread] Current Thread [Next in Thread]