Array.BinarySearch() return value - c#

I have the following array:
double[] list = new double[] {0,0,100,100}
Why if I search for 29.6 I get -3?
Array.BinarySearch(list, 29.6)
I expected +1 or -1.
The Array.BinarySearch() documentation for the return parameter says:
The index of the specified value in the specified array, if value is found. If value is not found and value is less than one or more elements in array, a negative number which is the bitwise complement of the index of the first element that is larger than value. If value is not found and value is greater than any of the elements in array, a negative number which is the bitwise complement of (the index of the last element plus 1).
But it does not says too much to me.

If value is not found and value is less than one or more elements in array, a negative number which is the bitwise complement of the index of the first element that is larger than value.
The first element which is larger than 29.6 is 100, which has index of 2.
~2 is -3.

You can use the '~' to take the bitwise complement which will give you the index of the first item larger than the search item.
If the Array does not contain the specified value, the method returns
a negative integer. You can apply the bitwise complement operator (~)
to the negative result (in Visual Basic, Xor the negative result with
-1) to produce an index. If this index is greater than or equal to the size of the array, there are no elements larger than value in the
array. Otherwise, it is the index of the first element that is larger
than value.
From the MSDN
Thus if you had:
var pos = Array.BinarySearch(list, 29.6);
You can check:
if (pos < 0)
{
Console.WriteLine("Not found, the result was {0} which is index {1}", pos, ~pos);
}
Which, in your case, means your -3 would indicate the index 2 is the first item larger than your search target.

Here is your answer:
"a negative number which is the bitwise complement of the index of the first element that is larger than value."
So in your case, your searched value (29.6) is less then 100 which is the 3rd element in your array list, the complement of 3 is -3, which is the answer you got.
Here I extended your example and created another array list (list2) with some different values then I searched same value like you 29.6, now this 29.6 value is smaller then 100 but greater then 25, and in my array list 100 is on position 4 and its complement is -4.
So I get the result -4, if I have searched 20 in my array list I would have get answer -3.
double[] list = new double[] { 0, 0, 100, 100 };
double[] list2 = new double[] { 10, 15, 25, 100 };
int result = Array.BinarySearch(list, 29.6);
int result2 = Array.BinarySearch(list2, 29.6);
Response.Write("Your answer result:" + result.ToString() + "<br/>");
Response.Write("Your answer result2:" + result2.ToString());
My Code result:
Your answer result : -3
Your answer result2: -4
I hope this helps.

Related

Finding All Combinations of a Multidimention Array with a Max Value in C#

Let's say I have an int[8,6] array which can have the maximum value of 255 per cell and I want to find all combinations of this array.
What is the most efficient way to accomplish this?
For array size N (1D array for simpliciry, 2D case works similar) and maximum value M there are M^N possible combinations. Every combination corresponds to value in range 0..M^N-1, so we can just walk throug this range and get combination for every value. Of course, it is possible for reasonable small values of N and M.
Python-like pseudocode:
int A[N]
P = M**N #math.intpower(M, N)
for i in range(P):
t = i
for k in range(N): #number of cells, number of digits in counter value
A[k] = t % M # value in k-th cells of result for variant number i
t = t // M #integer division
Note that for base M=256 you perhaps don't need to use division - needed values are just bytes of multibyte representation of big number in base 256

prefer high index number than lower one in an array

Assuming that I have these two sorted arrays with 5 cells:
The numbers in the array are between 2 and 14 ( 2 and 14 included and they are integers )
Now, I need to give a rank to each array from [0,100] when the lowest array will be:
[2,2,2,2,2] and the highest will be [14,14,14,14,14]
Now the thing is: the index is important so for example if we take a look at this these arrays:
1) [2,2,2,2,10]
2) [8,8,8,8,9]
So the 1st one is better than the the 2nd and will get an higher score.
And if there's a tie in the index ( from right to left ) for example:
1) [3,4,5,10,13]
2) [3,4,7,10,13]
So index numbers: 3 and 4 are the same, but since 7 is higher than 5. so in that case the 2nd array will have an higher score.
I'm struggling with the math, I mean I want to do it efficient, now I can do something like:
2^array[i] but it won't be efficient, so the main thing I managed to do is
double rank = 0;
for (int i = 0; i < 5; i++)
{
rank += (double)array[i] / 14 + i;
}
because if array[i] can be between 2 and 14, so 1/7 <= array[i]/14 <= 1
so I thought that if I'll add + i each iteration, the next iteration will be greater than all the previous ones, but it's mistake.
I'll be glad for some help in here.
You are essentially describing a base-13 number. Each "digit" (array position) represents one of 13 distinct, ordered values.
You can calculate a ranking by converting the array to a 5 digit, base 13 value:
Subtract 2 from each array element's value to normalize the element value to the range 0..12.
Give each array element a score = (normalized element value) * (13 raised to the array index power). 1)
Add up the scores.
1) Or raised to Array.Length - array index, depending on which side of the array should be the least significant.

Find the minimum of a number sequence with negative numbers with Linq

The following code doesn't give the expected minimum -1. Instead I get 0.
Do you know why?
class MainClass
{
public static void Main (string[] args)
{
string numbers = "-1 0 1 2 3 4 5";
Console.WriteLine (numbers.Split (' ')[0]); // output: -1
string max = numbers.Split(' ').Max();
string min = numbers.Split(' ').Min();
Console.WriteLine("{0} {1}", max, min); // output: "5 0"
}
}
I've not fully defined an answer yet but it appears to be because the - isn't accounted for.. you can confirm this with CompareOrdinal
Console.WriteLine(String.CompareOrdinal("-1", "0")); // -3 meaning -1 min
Console.WriteLine(String.Compare("-1", "0")); // 1 meaning 0 min
Either way, you are trying to compare numbers so you should treat them as numbers so similar subtleties dont appear.
Attempted explanation...
String implements IComparable<string> so String.Min uses that implementation (see remarks). Which in turn uses CompareTo,
Now in the notes for this method
Character sets include ignorable characters. The CompareTo(String) method does not consider such characters when it performs a culture-sensitive comparison. For example, if the following code is run on the .NET Framework 4 or later, a comparison of "animal" with "ani-mal" (using a soft hyphen, or U+00AD) indicates that the two strings are equivalent.
(Emphasis mine)
As you see. the - is ignored hence 0 which has a smaller value in an ascii table is used for the comparison
It's a string so Getting max from string is totally different than getting max from a number. For instance if You would have an array like below
char[] someCharArray = new char[] { '1', '12', '2' }
calling Max() on this array would result with 2 as 2 is "higher" in string order than 12.
Thinking about Max/Min value from string/char You need to think about alphabetical order. If You have a colection of letters A-Z, calling Min() will return A, calling Max() will return Z.
To get Max/Min in numerical order You need to cast to some Number type like int.
See below:
string numbers = "-1 0 1 2 3 4 5";
int min = numbers.Split(' ').Select(x => int.Parse(x)).Min();
Console.WriteLine(min); // gives You -1
There are two reasons for this behaviour:
You are sorting strings instead of numbers. This means that behind the scenes, Linq is using String.CompareTo() to compare the strings.
String.CompareTo() has special behaviour for -, which it treats as a HYPHEN and not a MINUS. (Note: This hyphen should not be confused with a soft hyphen which has the character code U00AD.)
Consider this code:
Console.WriteLine("-1".CompareTo("0")); // 1
Console.WriteLine("-1".CompareTo("1")); // 1
Console.WriteLine("-1".CompareTo("2")); // -1
Notice how, counter-intuitively, the "-1" is AFTER "0" and "1" but BEFORE "2".
This explains why when ordering the strings, the "-1" is neither the max nor the min.
Also see the answer to this question for more details.

Custom order by, is it possible?

I have the following collection:
-3, -2, -1, 0, 1, 2, 3
How can I in a single order by statement sort them in the following form:
The negative numbers are sorted first by their (absolute value) then the positive numbers.
-1, -2, -3, 0, 1, 2, 3
Combination sorting, first by the sign, then by the absolute value:
list.OrderBy(x => Math.Sign(x)).ThenBy(x => Math.Abs(x));
or:
from x in list
orderby Math.Sign(x), Math.Abs(x)
select x;
This is conceptually similar to the SQL statement:
SELECT x
FROM list
ORDER BY SIGN(x), ABS(x)
In LINQ-to-Objects, the sort is performed only once, not twice.
WARNING: Math.Abs(x) will fail if x == int.MinValue. If this marginal case is important, then you have to handle it separately.
var numbers = new[] { -3, -2, -1, 0, 1, 2, 3 };
var customSorted = numbers.OrderBy(n => n < 0 ? int.MinValue - n : n);
The idea here is to compare non-negative numbers by the value they have. And compare negative numbers with the value int.MinValue - n which is -2147483648 - n and because n is negative, the higher negative number we, the lower negative result the outcome will be.
It doesn't work when the list itself contains the number int.MinValue because this evaluates to 0 which would be equal to 0 itself. As Richard propose it could be made with longĀ“s if you need the full range but the performance will be slightly impaired by this.
Try something like (VB.Net example)
Orderby(Function(x) iif(x<0, Math.Abs(x), x*1000))
...if the values are <1000
You could express it in LINQ, but if I were reading the code two years later, I'd prefer to see something like:
list.OrderBy(i=>i, new NegativeThenPositiveByAscendingAbsoluteValueComparer());
You will need to implement IComparer.

What is the difference between Array.GetLength() and Array.Length?

How do you use the Array.GetLength function in C#?
What is the difference between the Length property and the GetLength function?
GetLength takes an integer that specifies the dimension of the array that you're querying and returns its length. Length property returns the total number of items in an array:
int[,,] a = new int[10,11,12];
Console.WriteLine(a.Length); // 1320
Console.WriteLine(a.GetLength(0)); // 10
Console.WriteLine(a.GetLength(1)); // 11
Console.WriteLine(a.GetLength(2)); // 12
For 1-dimensional arrays Length and GetLength(0) are exactly the same.
For arrays of higher rank Length is the product of all GetLength(0..Rank-1) values, in other words it is always the total number of fields.
The .Length property returns the number of elements in an array, whether it be one dimensional or multidimensional. That is a 2x6 array will have length of 12.
The .GetLength(0) method returns number of elements in the row direction in a multidimensional array. For a 2x6 array that is 2.
The .GetLength(1) method returns number of elements in the column direction in a multidimensional array. For a 2x6 array that is 6.
These do not return an actual element value, as stated by the chosen answer above.
GetLength returns the length of a specified dimension of a mulit-dimensional array.
Length returns the sum of the total number of elements in all the dimensions.
For a single-dimensional array, Length == GetLength(0)
For a two-dimensional array, Length == GetLength(0) * GetLength(1)
etc.
In mathematical term, we call as m rows and n columns, so the results is product of m*n for a two dimensional array. In this case GetLength(0) = m rows and GetLength(1)= n columns. For e.g see below example
string[,] stocks ={{"RELIND","Reliance Industries","1006.30"},{"TATMOB","Tata Mobiles","504.10"},{"ALST","Allstate","800.00"}, {"GE","GE Motors","810.00"}
};
The stocks arrays return GetLength(0)= 4 and GetLength(1)=3 and length =12

Categories

Resources