2

I'm trying to replace the values in array1 following this Logic:

  1. If the values are greater than one use just the decimal value.
  2. If it's exactly 1 stay at 1
  3. If 0 stay 0
  4. If neg make positive and follow the logic

The code I used was:

array1=[0.5 1.3 1.0 0.0 -0.2 -2.78]
array1(array1>1)=mod(abs(array1),1)

what I expected to get is array1 = [0.5 0.3 1.0 0.0 0.2 0.78]

But I get an error: =: nonconformant arguments (op1 is 1x1, op2 is 1x5) how can I fix this?

PS: I'm using Octave 5.2 which is similar to Matlab

Rick T
  • 3,349
  • 10
  • 54
  • 119

2 Answers2

3

This causes an Unable to perform assignment-error because left and right side of the assignment differ in size: You need to use the logical indexing on both sides array1>1.

array1=[0.5 1.3 1.0 0.0 -0.2]
% create logical vector for indexing
lg = array1 > 1
% replace elements
array1(lg) = mod( abs(array1(lg)) ,1)

This should work in MATLAB + Octave. You can also split the different operations :

% ensure positiveness
array1 = abs(array1);
% force to one
lg = array1 > 1;
array1(lg) = mod(array(1),1);

this returns array1 = 0.5000 0.3000 1.0000 0 0.20

If you absolutely want to stick to your approach, you can use a little trick: add +1e-10 to the second input of the mod function to let 1 "survive" the operation ;)

array1 = mod( abs(array1) ,1+1e-10)

This trick will yield slightly different results because the modulus is 1.0000000001 and not 1. The error will be higher, the higher the input number. However, from your example-array I would guess that this risk could be OK.

max
  • 3,915
  • 2
  • 9
  • 25
  • I don't understand why you've suggested the OP wants a solution different to what they've specifically defined in the 2nd half of your answer? And your "trick" gives a different (albeit only slightly) output by not using mod base 1. This is a correct answer up until the first code block then I think it needs a bit of thought! – Wolfie Oct 30 '20 at 08:32
  • @Wolfie ok I just wanted to give him/her credit since he/her got me where I needed to get to. – Rick T Oct 30 '20 at 09:03
  • @Wolfie thx, I adjusted it raised a word of warning to the "tick" ;) – max Oct 31 '20 at 08:18
1

max's answer got me where I needed to get to here's what I used.

array1=[0.5 1.3 1.0 0.0 -0.2 -2.63]

array1=abs(array1) %1) make array positive
lg = array1 > 1 %2) create logical vector for indexing
array1(lg) = mod( abs(array1(lg)) ,1) %3) replace elements
array1 =

   0.50000   1.30000   1.00000   0.00000  -0.20000  -2.63000

array1 =

   0.50000   1.30000   1.00000   0.00000   0.20000   2.63000

lg =

  0  1  0  0  0  1

array1 =

   0.50000   0.30000   1.00000   0.00000   0.20000   0.63000
Rick T
  • 3,349
  • 10
  • 54
  • 119