Question

I noticed a funny behaviour with Matlab-FI numbers. It occurs only with 1-bit, signed numbers (a datatype that does not make a lot of sense in practice). I'm aware that multiplying a double with a fi is not a good practice and the behaviour may even depend on the Matlab version, but I would expect the behaviour to be the same independent of the number of bits. This seems to be consistent in versions 2011b, 2013a and 2013b and I would like to understand why it happens that way.

Example 1: -1 can be representet as 1-bit, signed. However the result has a fraction-part of -2 which would allow only numbers [-8, -4, 0, 4]

>> a = fi(-1,1,1,0)
a = -1
      s1,0

>> 1*a
ans = 0
      s2,-2

Example 2: A 1-bit, unsigned behaves as expected, the fraction-part is unchanged

>> b = fi(1,0,1,0)
b = 1
      u1,0

>> 1*b
ans = 1
      u2,0

Example 3: A 2-bit, signed behaves as expected, the fraction-part is unchanged, the integer-part is extended

>> c = fi(-2,1,2,0)
c = -2
      s2,0

>> 1*c
ans = -2
      s4,0

Example 4: Another 1-bit, signed showing a similar behaviour as in example 1.

>> d = fi(-0.5,1,1,1)
d = -0.5000
      s1,1

>> 1*d
ans = 0
      s2,-1
Was it helpful?

Solution

When matlab is multiplying numbers with different format, it is changing the first of all modifying the formats. If you convert the 1 to the same format as your value, sometimes the number one in this format is 0, so it makes sense that the product is zero, and everything is as expected.

Example 1

a = fi(-1,1,1,0); a_one = fi(1,1,1,0); disp([a, a_one, a*a_one])
    -1     0     0

          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 1
        FractionLength: 0

Example 2

b = fi(1,0,1,0); b_one = fi(1,0,1,0); disp([b, b_one, b*b_one])
     1     1     1

          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Unsigned
            WordLength: 1
        FractionLength: 0

Example 3

c = fi(-2,1,2,0); c_one = fi(1,1,2,0); disp([c, c_one, c*c_one])
    -2     1    -2

          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 2
        FractionLength: 0

Example 4

d = fi(-0.5,1,1,1); d_one = fi(1,1,1,1); disp([d, d_one, d*d_one])
  -0.500000000000000                   0                   0

          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 1
        FractionLength: 1

OTHER TIPS

Disclaimer: The following is the (slightly edited) answer from MathWorks support which I'm adding for completeness. In brief it turns out that this is not limited to 1-bit datatypes, but (as pointed out by sebas) to the double constant being cast to the other operand and saturating there, notably without warning, but according to spec.


It turns out that the double constant value (e.g., 1) is cast to a FI type prior to the math operation (e.g. *), using the signedness and wordlength of the other operand. However, the new FI type uses a "best precision" fraction length instead of the fraction length of the other operand.

Here is some equivalent MATLAB code with the explicit fi() constructor illustrating this:

Example 1.

>> a = fi(-1,1,1,0)
a =
    -1
    s1,0

>> fi(1,a.SignednessBool,a.WordLength) * a
ans =
    0
    s2,-2

>> 1*a
ans =
    0
    s2,-2

Example 2.

>> b = fi(1,0,1,0)
b =
    1
    u1,0

>> fi(1,b.SignednessBool,b.WordLength) * b
ans =
    1
    u2,0

>> 1 * b
ans =
    1
    u2,0

Example 3.

>> c = fi(-2,1,2,0)
c =
    -2
    s2,0

>> fi(1,c.SignednessBool,c.WordLength) * c
ans =
    -2
    s4,0

>> 1 * c
ans =
    -2
    s4,0

Example 4.

>> d = fi(-0.5,1,1,1)
d =
    -0.5000
    s1,1

>> fi(1,d.SignednessBool,d.WordLength) * d
ans =
    0
    s2,-1

>> 1*d
ans =
    0
    s2,-1

I hope these examples help clarify the issue with the implicit type casting of a double constant value (e.g., 1).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top