C# Strange behavior with arrays and Random.NextDouble() - c#

I have the following code in the main() method:
const int Length = 20;
const int NumberOfExperiments = 100;
static void Main(string[] args)
{
Random gen = new Random();
double[][] arr = new double[NumberOfExperiments][];
for (int j = 0; j < NumberOfExperiments; ++j)
{
arr[j] = new double[Length + 4];
for (int i = 0; i < Length; ++i)
{
arr[j][i] = gen.NextDouble();
}
arr[j][Length] = bubbleSort(arr[j]);
arr[j][Length + 1] = insertSort(arr[j]);
arr[j][Length + 2] = arr[j][Length] - arr[j][Length + 1];
arr[j][Length + 3] = arr[j][Length + 2] * arr[j][Length + 2];
foreach(double memb in arr[j]){
Console.WriteLine("{0}", memb);
}
Console.ReadKey();
}
WriteExcel(arr, "sorting");
Console.ReadKey();
}
After the first ReadKey() i have the following output:
0
0
0
0
0.046667384
0.178001223
0.197902503
0.206131403
0.24464349
0.306212793
0.307806501
0.354127458
0.385836004
0.389128544
0.431109518
0.489858235
0.530548627
0.558604611
0.647516463
0.762527595
0.874646365
152
-151.1253536
22838.87251
I don't know why the first several elements of array are filled with 0. The first iteration always begins with i=0(or j=0), so it's Ok.
Functions bubbleSort() and insertSort() work correctly and return the number of swaps.
I have used C# for several years, but I really can't understand why this code doesn't work.

When you create the "row", you do this:
arr[j] = new double[Length + 4];
But then loop like this:
for (int i = 0; i < Length; ++i)
So the last 4 elements are left with the default value (0). When you sort, these elements go to the beginning.

It looks like bubbleSort() gets an array and sorts it, at the time of the call the last 4 elements are empty (set to 0), so they go to the beginning in the result. Check if bubbleSort() uses Array.Length somewhere and make sure it subtracts 4 there.

Related

SubArray of a 2d array with non-zero lower bounds

The extension :
public static T[,] SubArray<T>(this T[,] values, int row_min, int row_max, int col_min, int col_max)
{
int num_rows = row_max - row_min + 1;
int num_cols = col_max - col_min + 1;
T[,] result = new T[num_rows, num_cols];
int total_cols = values.GetUpperBound(1) + 1;
int from_index = row_min * total_cols + col_min;
int to_index = 0;
for (int row = 0; row <= num_rows - 1; row++)
{
Array.Copy(values, from_index, result, to_index, num_cols);
from_index += total_cols;
to_index += num_cols;
}
return result;
}
work well for 2D arrays arrays whose GetLowerBound(0) and GetLowerBound(1) are equal to zero. For instance if
int[,] arr1 = new int[5, 4];
for (int i = 0; i < 5; ++i)
{
for (int j = 0; j < 4; ++j)
{
arr1[i, j] = i + j;
}
}
var arr1sub = arr1.SubArray(2, 3, 1, 3);
Then arr1sub is the 2d array with 2 rows and 3 colums (boths with indexes starting at 0)
3 4 5
5 6 7
Now if I look at the case where the initial array as indexes not starting at zero :
int[,] arr2 = (int[,])Array.CreateInstance(typeof(int), new int[] { 5, 4 }, new int[] { 3, 1 });
for (int i = arr2.GetLowerBound(0); i <= arr2.GetUpperBound(0); ++i)
{
for (int j = arr2.GetLowerBound(1); j <= arr2.GetUpperBound(1); ++j)
{
arr2[i, j] = i - arr2.GetLowerBound(0) + j - arr2.GetLowerBound(1);
}
}
var arr2sub = arr2.SubArray(5, 6, 2, 4);
the last line of previous code snippet will trigger an exception in the SubArray extension function at the line
Array.Copy(values, from_index, result, to_index, num_cols);
for row equal to zero.
I understand of the 2d array arr1 (with zero based indexes) is layed out in memory but not how the 2d array arr2 (with non-zero-based indexes) is layed out in memory, hence my use of Array.Copy must be wrong in this case, but I don't see why.
You are not calculating total_cols and from_index correctly.
public static T[,] SubArray<T>(this T[,] values, int row_min, int row_max, int col_min, int col_max)
{
int num_rows = row_max - row_min + 1;
int num_cols = col_max - col_min + 1;
T[,] result = new T[num_rows, num_cols];
int total_cols = values.GetLength(1);
int from_index = (row_min - values.GetLowerBound(0)) * total_cols + (col_min - values.GetLowerBound(1)) + values.GetLowerBound(0);
int to_index = 0;
for (int row = 0; row <= num_rows - 1; row++)
{
Array.Copy(values, from_index, result, to_index, num_cols);
from_index += total_cols;
to_index += num_cols;
}
return result;
}
total_cols is the obvious one; as for from_index, I cannot find any documentation on that, but it would appear that sourceIndex in Array.Copy starts counting from sourceArray.GetLowerBound(0) and not from zero, which is not necessarily immediately obvious given that this index keeps growing across rows and columns.

C# Programming task

Hello i've got a easy programming task in C# but im stuck on the last part. I need to make 2 arrays that have random numbers (3x3) and on the end i need to sum them up in one number.
So its: array1 with 3 numbers + array2 with 3 numbers = array3 with all the array numbers addition. Can somebody please help me?
My code is:
static void Main(string[] args)
{
int[,] pole1 = new int[3, 3];
int[,] pole2 = new int[3, 3];
int[,] pole3 = new int[3, 3];
Random random1 = new Random();
Console.WriteLine("Pole 1 je: ");
for (int a = 0; a <= 2; a++)
{
for (int b = 0; b <= 2; b++)
{
pole1[a, b] = random1.Next(1, 9);
Console.Write(pole1[a, b]);
}
Console.WriteLine();
}
Console.WriteLine("Pole 2 je: ");
for (int a = 0; a <= 2; a++)
{
for (int b = 0; b <= 2; b++)
{
pole2[a, b] = random1.Next(1, 9);
Console.Write(pole2[a, b]);
}
Console.WriteLine();
}
Console.WriteLine("Součet polí je: ");
for (int a = 0; a <= 2; a++)
{
for (int b = 0; b <= 2; b++)
{
pole3[a, b] = (pole1[a, b] + pole2[a, b]);
Console.Write(pole3[a, b]);
}
Console.WriteLine();
}
Console.ReadKey();
}
}
I've got the two arrays but idk how to sum them up.
I think your code is working properly
Console.Write(pole1[a, b] + "\t"); // Add "\t"
Console.Write(pole2[a, b] + "\t"); // Add "\t"
Console.Write(pole3[a, b] + "\t"); // Add "\t"
UPDATE : if you want like bellow
Array 1 : 373
Array 2 : 176
Result : 549
Last loop will be
for (int a = 0; a <= 2; a++)
{
int sum = (pole1[a, 0] + pole2[a, 0]) * 100 + (pole1[a, 1] + pole2[a, 1]) * 10 + (pole1[a, 2] + pole2[a, 2]) ;
pole3[a, 0] = sum / 100;
pole3[a, 1] = (sum - pole3[a, 0] * 100) / 10;
pole3[a, 2] = sum - (pole3[a, 0] * 100) - (pole3[a, 1] * 10);
Console.Write($"{pole3[a, 0]}" + "\t" + $"{pole3[a, 1]}" + "\t" + $"{pole3[a, 2]}");
Console.WriteLine();
}
The Sum() method in Linq is a good goto if you want to sum up an array, however multi-dimensional arrays do not implement IEnumerable<T> by default, which can cause a few bumps in the road. Luckily Linq provides us a way to specify the type using the Cast<T> method like so:
int total = pole1.Cast<int>().Sum() + pole2.Cast<int>().Sum();
Note that I've replaced <T> with <int> as we are using generics (read more on MSDN).

C# Transcribing data to the second table and reversing them

I am will be grateful for help because I am not sure how make this program.
I should code program with two tables. The first will fill it with numbers Random tab = new Random();. After that I should reverse numbers and fill them into second table.
I made first functionality but I am not sure how make start with second table?
class Program
{
static void Main(string[] args)
{
int[] tablica1 = new int[20];
Random tab = new Random();
for (int i = 0; i < 20; i++)
{
tablica1[i] = tab.Next(20);
Console.WriteLine("Tablica wylosowała nastepujace elementy:");
Console.WriteLine(tablica1[i]);
}
Console.Read();
int[] tablica2 = new int[20];
/*for (int i = 20; i > 0; i--)
{
}
*/
}
}
You didn't quite describe what exactly happens when you run the code, but I think the problem is with this part - as this should give you an IndexOutOfRangeException:
for (int j = tablica2.Length; j > 1 ; j--)
{
tablica2[j] = tablica1[20-j];
Console.WriteLine(tablica2[j]);
}
The array indices go form 0 to tablica2.Length - 1 (one less then the length, so the index tablica2.Length is outside the array).
Your loop goes in reverse from tablica2.Length two 2 for some reason.
So as soon as it starts executing, j is 20, but the highest index is 19.
Change the loop so it goes the full range, and change the loop body so that you don't access out-of-range indices, in one of two ways:
for (int j = tablica2.Length - 1; j >= 0 ; j--) // goes from 19 to 0
{
tablica2[j] = tablica1[tablica1.Length - j - 1];
}
or
for (int j = tablica2.Length; j > 0 ; j--) // goes from 20 to 1
{
tablica2[j - 1] = tablica1[tablica1.Length - j];
}
static void Main(string[] args)
{
int[] tablica1 = new int[20];
Random tab = new Random();
for (int i = 0; i < 20; i++)
{
tablica1[i] = tab.Next(20);
Console.WriteLine("Tablica wylosowała nastepujace elementy:");
Console.WriteLine(tablica1[i]);
}
Console.Read();
int[] tablica2 = new int[20];
for (int i = 20; i > 0; i--)
{
tablica2[i]=tablica1[20-i];
}
}
}
#Sinatr Thank You for this topic. It was really helpful but there is only one table.
#Filip Milovanović Yes, I have to make two two tables :) After reserving first, I should put elements from first to second. I changed this for, but in console I am still able to see only first one. :(
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Randomy1
{
class Program
{
static void Main(string[] args)
{
int[] tablica1 = new int[20];
Random tab = new Random();
for (int i = 0; i < 20; i++)
{
tablica1[i] = tab.Next(20);
Console.WriteLine(tablica1[i]);
}
int[] tablica2 = new int[20];
for (int j = tablica2.Length; j > 1 ; j--)
{
tablica2[j] = tablica1[20-j];
Console.WriteLine(tablica2[j]);
}
Console.Read();
}
}
}
I think this would work
for (int i = 0; i < 20; i++)
{
tablica2[i] = tablica1[20 - (i + 1)];
Console.WriteLine("Tablica 1st :: " + tablica1[i] + " Tablica 1 Reverse " + tablica1[20 - (i + 1)] + " Tablica 2 " + tablica2[i]);
}

Microsoft.Office.Interop IndexOutOfRangeException

The below IndexOutOfRangeException is not letting my code run (it compiles). While I understand this kind of exception (array indexes etc) the issue is, what I am trying to do is simply update the String subsection2 with the value in cell B[excelrow]. For some reason, there is an index out of bounds exception which to me does not make sense. Neither subsection2 or excelrow is part of an array. The only array I can think of is the excel array, but excelrow is an integer with value of 3, it should updated to row B3, and so on. (I've even tried updating with B3 directly and I get the same error).
To help you out further with context, this method called createsource takes as input the excel spreadsheet and the total rows in that sheet. It does the below code to output a 2D array containing in the first dimension the excel index of each new order (each different customer), and the 2nd dimension is the number of items ordered per customer.
The method for the code is below:
private int[,] createsource(Microsoft.Office.Interop.Excel.Worksheet xlWorksheet, int totalRows)
{
String subsection = "";
object subsection2 = "";
int orders = 0;
//figures out how many different pages there are going to be
for (int n = 3; n < totalRows + 1; n++)
{
if (!(xlWorksheet.get_Range("B" + n.ToString()).Text == subsection))
{
subsection = xlWorksheet.get_Range("B" + n.ToString()).Text;
orders++;
}
}
MessageBox.Show(orders.ToString());
int[,] source = new int[orders, 2];
int excelrow = 3;
subsection2 = xlWorksheet.get_Range("B" + excelrow.ToString()).Text;
int i;
for (i = 0; i < orders + 1; i++)
{
int j = 1;
if (excelrow == totalRows + 1)
{
break;
}
//Out of bounds exception is found in the below if statement updating subsection2:
if (!(xlWorksheet.get_Range("B" + excelrow.ToString()).Text == subsection2))
{
source[i, 0] = excelrow;
//MessageBox.Show(xlWorksheet.get_Range("B" + excelrow.ToString()).Text.ToString());
subsection2 = xlWorksheet.get_Range("B" + excelrow.ToString()).Text;
excelrow++;
}
for (int iter = 0; iter < 1;)
{
if (excelrow == totalRows + 1)
{
break;
}
if (xlWorksheet.get_Range("B" + excelrow.ToString()).Text == subsection2)
{
excelrow++;
j++;
}
if (!(xlWorksheet.get_Range("C" + excelrow.ToString()).Text == subsection2))
{
subsection2 = xlWorksheet.get_Range("C" + excelrow.ToString()).Text;
iter = 1;
}
}
source[i, 1] = j;
}
MessageBox.Show(source[2, 0].ToString());
return source;
}
I see the problem. You're declaring source as:
int[,] source = new int[orders, 2];
... okay, but look at your loop:
for (i = 0; i < orders + 1; i++)
... which later feeds into:
source[i, 0] = excelrow;
Okay, so if orders = 100, you've declared a 100 long array, going from 0-99. Then your loop, you go from 0 to "less than 100+1", aka 0-100. When you get to the last loop, you're using a value of i=100, and trying to put it into the array spot that doesn't exist.
You need to either decrease your loop by one, or increase your array size by 1.

C# array printing

I am trying to achieve the following:
User enters 100 numbers and then the numbers are printed in 3 columns.
This is what I have so far, it works but it does not print the last value of the array.
What am I doing wrong?
static void Main(string[] args)
{
int digit = 0;
const int LIMIT = 100;
int[] row = new int[LIMIT];
for (int i = 0; i < row.Length; i++)
{
Console.WriteLine("Geef getal nummer " + (i + 1) + " in: ");
digit = int.Parse(Console.ReadLine());
row[i] = digit;
}
for (int i = 0; i < row.Length - 2; i+=3)
{
Console.WriteLine(row[i] + "\t" + row[i + 1] + "\t" + row[i + 2]);
}
}
Use this print instead
for (int i = 0; i < row.Length; i++)
{
Console.Write(row[i] + "\t");
if (i % 3 == 2)
Console.WriteLine();
}
Your issue is that you don't simply use Console.Write, and try to write your lines in one shot.
In fact, it would be even cleaner to use a StringBuilder here.
Replace
for (int i = 0; i < row.Length - 2; i+=3)
{
Console.WriteLine(row[i] + "\t" + row[i + 1] + "\t" + row[i + 2]);
}
by
StringBuilder sb = new StringBuilder();
int count = 0;
for (int i = 0; i < row.Length; i++)
{
count++;
if (count == 3)
{
sb.AppendLine(row[i])
count = 0;
}
else
sb.Append(row[i]).Append('\t');
}
Console.WriteLine(sb.ToString());
I think it's pretty explicit, but if you need clarifications, feel free to ask. Of course, the use of count here is pretty scholar, a real program could use % operator, like shown in other answers.
You have wrong condition in for loop. If you don't mind LINQ, you can use the following:
foreach (string s in row.Select((n, i) => new { n, i })
.GroupBy(p => p.i / 3)
.Select(g => string.Join("\t", g.Select(p => p.n))))
Console.WriteLine(s);
If you're not ok with LINQ, you can do this:
int colIndex = 0;
foreach (int n in row)
{
Console.Write(n);
if (colIndex == 2)
Console.WriteLine();
else
Console.Write('\t');
colIndex = (colIndex + 1) % 3;
}
jonavo is correct.
after 96+3 = 99
and you have done row.length-2, change it to row. length+2.
and in print dont print if the i+1 or I+2 >= max
It doesn't print it because 100 is not evenly divisible by 3 and your for-loop increases the variable by 3 on each iteration, so the last element wil be skipped.
Maybe this after the loop:
int rest = row.Length % 3;
if(rest > 0)
Console.WriteLine(row[row.Length - rest] + "\t" + row.ElementAtOrDefault(row.Length - rest + 1));
Its because of your index.
Your running index i goes from
0, 3, 6, 9, ... 96, 99
So this would output the array positions:
0,1,2 3,4,5 6,7,8 9,10,11 ... 96,97,98 99,100,101 (index out of bounds)
row.Length equals 100, so your loop-condition (i < row.Length - 2) is correct, but even better would be (i < row.Length - 3).
So your problem is how to print the last number... You see, you have 3 columns for 100 digits. This makes 33 rows and than there is one digit left.
Maybe you just add some Console.WriteLine(row[row.Length-1]); beneeth your loop.
Looks like you've got a lot of options at your disposal. Here's an approach using nested loops:
int numCols = 3;
for (int i = 0; i < row.Length; i += numCols)
{
for (int j = i; j < i + numCols && j < row.Length; j++)
{
Console.Write(row[j] + "\t");
}
Console.WriteLine();
}
Try this code.
Using this loop you can also change the number of rows/columns without code changes. Also, using the temporary buffer you output to the console an entire row at a time.
static void Main(string[] args)
{
int digit = 0;
const int LIMIT = 10;
const int COLS = 3;
int[] row = new int[LIMIT];
for (int i = 0; i < row.Length; i++)
{
Console.WriteLine("Geef getal nummer " + (i + 1) + " in: ");
// Re-try until user insert a valid integer.
while (!int.TryParse(Console.ReadLine(), out digit))
Console.WriteLine("Wrong format: please insert an integer number:");
row[i] = digit;
}
PrintArray(row, COLS);
// Wait to see console output.
Console.ReadKey();
}
/// <summary>
/// Print an array on console formatted in a number of columns.
/// </summary>
/// <param name="array">Input Array</param>
/// <param name="columns">Number of columns</param>
/// <returns>True on success, otherwise false.</returns>
static bool PrintArray(int[] array, int columns)
{
if (array == null || columns <= 0)
return false;
if (array.Length == 0)
return true;
// Build a buffer of columns elements.
string buffer = array[0].ToString();
for (int i = 1; i < array.Length; ++i)
{
if (i % columns == 0)
{
Console.WriteLine(buffer);
buffer = array[i].ToString();
}
else
buffer += "\t" + array[i].ToString();
}
// Print the remaining elements
if (array.Length % columns != 0)
Console.WriteLine(buffer);
return true;
}
Just for completeness
Note that int.Parse(Console.ReadLine()) can throw an Exception if unexpected characters are typed. It's better to use int.TryParse() as documented here. This method don't throw an exception but return a boolean that report a successful conversion.
while (!int.TryParse(Console.ReadLine(), out digit))
Console.WriteLine("Wrong format: please insert an integer number:");
This code tell the user that the typed string can't be interpreted as an integer and prompt again until a successful conversion is done.

Categories