What Is The Purpose of Negative Modulus Operator Results? - operator-keyword

I was previously under the (naive) assumption that the modulus operator returned the remainder of division. I was apparently wrong, as -2 % 5 returns 3. I would have thought that 5 divides -2 zero times with -2 as the remainder.
Now I understand the mechanics of how this operation is performed, but my question is why? Could someone give me a link to something that explains why modulus and remainder are not synonymous, or an example of a situation where it would be useful?

The result is entirely correct. Modular arithmetic defines the following (I'll use "congruent" since I can't type the equal sign with three lines)
a congruent b mod c iff a-b is a multiple of c, i.e. x * c = (a-b) for some integer x.
E.g.
0 congruent 0 mod 5 (0 * 5 = 0-0)
1 congruent 1 mod 5 (0 * 5 = 1-1)
2 congruent 2 mod 5 (0 * 5 = 2-2)
3 congruent 3 mod 5 (0 * 5 = 3-3)
4 congruent 4 mod 5 (0 * 5 = 4-4)
5 congruent 0 mod 5 (1 * 5 = 5-0)
6 congruent 1 mod 5 (1 * 5 = 6-1)
...
The same can be extended to negative integers:
-1 congruent 4 mod 5 (-1 * 5 = -1-4)
-2 congruent 3 mod 5 (-1 * 5 = -2-3)
-3 congruent 2 mod 5 (-1 * 5 = -3-2)
-4 congruent 1 mod 5 (-1 * 5 = -4-1)
-5 congruent 5 mod 5 (-1 * 5 = -5-0)
-6 congruent 4 mod 5 (-2 * 5 = -6-4)
-7 congruent 3 mod 5 (-2 * 5 = -7-3)
...
As you can see, a lot of integers are congruent 3 mod 5:
..., -12, -7, -2, 3, 8, 13, ...
In mathematics, the set of these numbers is called the equivalence class induced by the equivalence relation "congruence". Our understanding of the remainder and the definition of the "mod" function are based on this equivalence class. The "remainder" or the result of a mod computation is a representative element of the equivalence class. By declaration we have chosen the smallest non-negative element (so -2 is not a valid candidate).
So when you read -2 mod 5 = x this translates to "Find the smallest non-negative x so that there exists an integer y with y * 5 = -2 - x", in concordance with the definition of congruence. The solution is y=1 and x = 3 as you can see by simply trying out other values for y.

a = n (mod m) is defined as a = n + m*t and it applies to negative numbers equally well. (Another to look at it is that a = n (mod m) means (a - n) is a multiple of m)
-2 = 3 (mod 5) because -2 = 3 - 5 (i.e. t = -1)
The convention is that the result of taking a modulo m is a number between 0 and m - 1 (inclusive)

The fundamental guarantee that you get is that
(a % b) + b * (a / b) == a
For signed values, there is no reason either sign should be the preferred outcome of a modulo or divide operation. Some languages fix one form, others leave it up to the implementation, so that the implementation can use whichever way the hardware happens to provide. The hardware instruction, in turn, may have been chosen to operate efficiently the hardware's representation of signed integers.
Generally, be very careful when using signed integers together with division, remainder and bit shift operations.

I guess it depends on whether you want your result rounded down or rounded towards 0:
2 / 5 = 0.4 = 5*0 + 2 works in both cases, whereas
-2 / 5 = -0.4 = 5*0 + -2 if you're rounding towards 0 (truncation),
-2 / 5 = -0.4 = 5*-1 + 3 if you're rounding down (floor).
Note that the result is always positive (for a positive divisor) in the second case and it would be useful, for example, when calculating an array index:
hashmapBuckets[getIntHash(obj) % hashmapBuckets.size].add(obj)
or normalizing an angle:
angle = angle % 360; //0-359
It is in fact the other case I'm having trouble finding practical examples for :)
--
Oh, and the Wikipedia page on the modulo operation has some nice graphs. Note that the remainder always has the same sign as the divisor for a floored division.

Think of modulo as an operator that wraps a line of length y (in terms of y % x) around a circle of x pegs. The remaining length of the line that doesn't fully wrap around x is the resultant.

Related

negative and positive distance in matlab

I have a 1 by N vector for example (N is 5):
x=[1,2,3,4,5];
I want to create an N-by-N matrix, M, where M(i,j)=x(i)-x(j) and M(j,i) = -1 * M(i,j)
Could anyone give a simple way without a loop?
You can use binary singleton expansion bsxfun:
bsxfun(#minus,x.',x)
or (in version 2016b or later) implicit expansion:
x.'-x
both will result in:
ans =
0 -1 -2 -3 -4
1 0 -1 -2 -3
2 1 0 -1 -2
3 2 1 0 -1
4 3 2 1 0
This method does exactly what you asked for - apply a function to all the combinations of a with b. In your case, a and b are simply x and itself, and the function is minus (which is written with # in bsxfun, or as simple operator - in an implicit expansion).
Since you want to subtract the column j from the row i, you should first write the column x (i.e. x.') that represents the row index, and then row x, that represents the column index.

i use factor(n) in matlab but it don't work for numbers like ((10^11-1)/11),for same number what can i do?

I use factor(n) in matlab but it don't work for numbers like ((10^11-1)/11) - what can I do? My source is here.
m=input('Enter your number: ');
i=0;
while (i<m)
if(isprime(i))
% sum=factor((10^(i-1)-1));
sum=factor((10^(i-1)-1)/i);
disp(sum);
end
i =i+1;
end
but for large n it returns errors!!
>> FactorGen
Enter your number: 45
3 3
3 3 11
3 3 11 101
3 3 3 7 11 13 37
3 3 11 41 271 9091
3 3 3 7 11 13 37 101 9901
Error using factor (line 26) When n is single or double, its maximum
allowed value is FLINTMAX.
Error in FactorGen (line 7) sum=factor((10^(i-1)-1));
I want the function factor((10^(i-1)-1)) to work for same number. How can I solve my problem?
I think this can be partially alleviated by converting your large number into uint64 format. For R2014b maximum integer that can be handled is:
n = intmax('uint64')
n = 1.8447e+19
While the maximum double that can be handled is:
n = flintmax('double')
n = 9.0072e+15
This can be verified by simple example. Let's use factor on the number larger than flintmax. First, try double:
factor(10^16)
Error using factor (line 26)
When n is single or double, its maximum allowed value is FLINTMAX.
Now, we try uint64:
factor(uint64(10^16))
ans = 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
So, using factor(uint64(x)) increases your limit by several orders. Indeed, there's no sense in using double format for factor function.
By the way, since using factor on large numbers may freeze your system, I suggest using this function:
function f = Factorize(n)
i = 0;
while mod(n,2) == 0
i = i + 1;
n = n/2;
f(i) = 2;
disp([2,n])
end
q = round(sqrt(double(n)));
q = q + 1 - mod(q,2);
for j = 3:2:q
while mod(n,j) == 0
i = i + 1;
f(i) = j;
n = n/j;
end
end
if n > 2;
i = i + 1;
f(i) = n;
end
It is much faster for large numbers and does not overload the system at large n
Hope that helps

Classifying multivariate data and giving new coordinate

Consider a below data set
Obs y x z
1 3 10 1
2 0 12-1
3 4 9 3
4 2 15 0
y is a dependent variable and the others are explanatory variables
I want to give total 4 observations a new coordinates based on some conditions, for example,
If y is in [0,3) give 1 to that y,
or if y is in [3,6), give 2 to that y.
Likewise,
If x is in [9,12), give 1 to that x,
or if x is in [12,16), give 2 to that x,
And do the similar for z.
As a result,
Obs y x z coordinate
1 3 10 1 (1,1,1)
2 0 12 1 (1,1,1)
3 4 9 3 (2,1,2)
4 2 15 0 (1,2,1)
I need these new coordinates as vectors for 4 observations.
I might be able to do this by 'loop' command, but it is too time consuming.
So I need to do this without 'loop' but with some commands related to vector.
Does anybody know how to do this?
While Dan's answer will work well if you only have two values for each coordinate based on a logical expression, if you have more complex logical requirements then I think that you want something similar to the following (which can easily be extended to cover more cases):
y = [ 3 0 4 2 ]';
x = [ 10 12 9 15 ]';
z = [ 1 1 3 0 ]';
coordinate = zeros(length(x), 3);
coordinate(y >= 0 & y < 3, 1) = 1;
coordinate(y >= 3 & y < 6, 1) = 2;
coordinate(x >= 9 & x < 12, 2) = 1;
coordinate(x >= 12 & x < 16, 2) = 2;
coordinate(z >= 0 & z < 3, 3) = 1;
coordinate(z >= 3 & z < 6, 3) = 2;
coordinate
results in
coordinate =
2 1 1
1 2 1
2 1 2
1 2 1
Where you can read each row off, for example coordinate(1, :) to get the first set of coordinates.
This also has the advantage that you can see where none of your rules match because the element in the coordinate matrix will be 0. You could alternatively use nan instead of zeros to create the coordinate matrix.
You can do this easily using logical indexing, in fact, this is pretty much answered here: Change elements of matrix based on condition
n=4;
coordinate = zeros(n,3);
%// y
coordinate(:,1) = (y > 3) + 1
%// x
coordinate(:,2) = (x > 12) + 1
etc...

Matlab random number range

I am struggling generating a random number within the range of x.
So say x is 4 the range would be -2 to 2 and if it was 6 then -3 to 3.
I know it is
rand() * something + somethingelse
You have to take out the mean of rand*x, that is x/2:
x = [1 2 3 4 5 6 7]
rand(1,numel(x)).*x-x/2
ans =
0.4172 -0.4283 0.7716 1.0149 -0.5978 0.4069 -2.9690
From where you left it is not hard to find the solution:
rand() * something + somethingelse
From left to right:
rand() : From 0 to 1
We want to make the range 4 times as wide, so we do:
rand()*4 : From 0 to 4
Now the width is correct, we just need to give it the correct location:
rand()*4-2: From -2 to 2

Efficiently generating unique pairs of integers

In MATLAB, I would like to generate n pairs of random integers in the range [1, m], where each pair is unique. For uniqueness, I consider the order of the numbers in the pair to be irrelevant such that [3, 10] is equal to [10, 3].
Also, each pair should consist of two distinct integers; i.e. [3, 4] is ok but [3, 3] would be rejected.
EDIT: Each possible pair should be chosen with equal likelihood.
(Obviously a constraint on the parameters is that n <= m(m-1)/2.)
I have been able to successfully do this when m is small, like so:
m = 500; n = 10; % setting parameters
A = ((1:m)'*ones(1, m)); % each column has the numbers 1 -> m
idxs1 = squareform(tril(A', -1))';
idxs2 = squareform(tril(A, -1))';
all_pairs = [idxs1, idxs2]; % this contains all possible pairs
idx_to_use = randperm( size(all_pairs, 1), n ); % choosing random n pairs
pairs = all_pairs(idx_to_use, :)
pairs =
254 414
247 334
111 146
207 297
45 390
229 411
9 16
75 395
12 338
25 442
However, the matrix A is of size m x m, meaning when m becomes large (e.g. upwards of 10,000), MATLAB runs out of memory.
I considered generating a load of random numbers randi(m, [n, 2]), and repeatedly rejecting the rows which repeated, but I was concerned about getting stuck in a loop when n was close to m(m-1)/2.
Is there an easier, cleaner way of generating unique pairs of distinct integers?
Easy, peasy, when viewed in the proper way.
You wish to generate n pairs of integers, [p,q], such that p and q lie in the interval [1,m], and p
How many possible pairs are there? The total number of pairs is just m*(m-1)/2. (I.e., the sum of the numbers from 1 to m-1.)
So we could generate n random integers in the range [1,m*(m-1)/2]. Randperm does this nicely. (Older matlab releases do not allow the second argument to randperm.)
k = randperm(m/2*(m-1),n);
(Note that I've written this expression with m in a funny way, dividing by 2 in perhaps a strange place. This avoids precision problems for some values of m near the upper limits.)
Now, if we associate each possible pair [p,q] with one of the integers in k, we can work backwards, from the integers generated in k, to a pair [p,q]. Thus the first few pairs in that list are:
{[1,2], [1,3], [2,3], [1,4], [2,4], [3,4], ..., [m-1,m]}
We can think of them as the elements in a strictly upper triangular array of size m by m, thus those elements above the main diagonal.
q = floor(sqrt(8*(k-1) + 1)/2 + 1/2);
p = k - q.*(q-1)/2;
See that these formulas recover p and q from the unrolled elements in k. We can convince ourselves that this does indeed work, but perhaps a simple way here is just this test:
k = 1:21;
q = floor(sqrt(8*(k-1) + 1)/2 + 3/2);
p = k - (q-1).*(q-2)/2;
[k;p;q]'
ans =
1 1 2
2 1 3
3 2 3
4 1 4
5 2 4
6 3 4
7 1 5
8 2 5
9 3 5
10 4 5
11 1 6
12 2 6
13 3 6
14 4 6
15 5 6
16 1 7
17 2 7
18 3 7
19 4 7
20 5 7
21 6 7
Another way of testing it is to show that all pairs get generated for a small case.
m = 5;
n = 10;
k = randperm(m/2*(m-1),n);
q = floor(sqrt(8*(k-1) + 1)/2 + 3/2);
p = k - (q-1).*(q-2)/2;
sortrows([p;q]',[2 1])
ans =
1 2
1 3
2 3
1 4
2 4
3 4
1 5
2 5
3 5
4 5
Yup, it looks like everything works perfectly. Now try it for some large numbers for m and n to test the time used.
tic
m = 1e6;
n = 100000;
k = randperm(m/2*(m-1),n);
q = floor(sqrt(8*(k-1) + 1)/2 + 3/2);
p = k - (q-1).*(q-2)/2;
toc
Elapsed time is 0.014689 seconds.
This scheme will work for m as large as roughly 1e8, before it fails due to precision errors in double precision. The exact limit should be m no larger than 134217728 before m/2*(m-1) exceeds 2^53. A nice feature is that no rejection for repeat pairs need be done.
This is more of a general approach rather then a matlab solution.
How about you do the following first you fill a vector like the following.
x[n] = rand()
x[n + 1] = x[n] + rand() %% where rand can be equal to 0.
Then you do the following again
x[n][y] = x[n][y] + rand() + 1
And if
x[n] == x[n+1]
You would make sure that the same pair is not already selected.
After you are done you can run a permutation algorithm on the matrix if you want them to be randomly spaced.
This approach will give you all the possibility or 2 integer pairs, and it runs in O(n) where n is the height of the matrix.
The following code does what you need:
n = 10000;
m = 500;
my_list = unique(sort(round(rand(n,2)*m),2),'rows');
my_list = my_list(find((my_list(:,1)==my_list(:,2))==0),:);
%temp = my_list; %In case you want to check what you initially generated.
while(size(my_list,1)~=n)
%my_list = unique([my_list;sort(round(rand(1,2)*m),2)],'rows');
%Changed as per #jucestain's suggestion.
my_list = unique([my_list;sort(round(rand((n-size(my_list,1)),2)*m),2)],'rows');
my_list = my_list(find((my_list(:,1)==my_list(:,2))==0),:);
end