Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
How would you express this loop in C# as a mathematical expression?
private string FormatBytes(long bytes)
{
string[] Suffix = { "B", "KB", "MB", "GB", "TB" };
int i;
double dblSByte = bytes;
for (i = 0; i < Suffix.Length && bytes >= 1024; i++, bytes /= 1024)
{
dblSByte = bytes / 1024.0;
}
return String.Format("{0:0.##} {1}", dblSByte, Suffix[i]);
}
You can calculate this mathematically by first working out the nearest smaller power of 1024 to the number:
int power = (int) Math.Log(bytes, 1024)
Then you can limit that number to the number of suffixes so you don't go past the end of the array:
int power = Math.Min(Suffix.Length-1, (int) Math.Log(bytes, 1024));
Then you work out what you should divide the original number by based on that power:
double div = Math.Pow(1024, power);
Then you can format the string using the suffix for the specified power of 1024:
return string.Format("{0:f1}{1}", bytes / div, Suffix[power]);
Putting this all together (and throwing in "PB" for petabytes):
private string FormatBytes(long bytes)
{
string[] Suffix = { "B", "KB", "MB", "GB", "TB", "PB" };
int power = Math.Min(Suffix.Length-1, (int) Math.Log(bytes, 1024));
double div = Math.Pow(1024, power);
return string.Format("{0:f1}{1}", bytes / div, Suffix[power]);
}
Et voila! Calculated mathematically without using a loop.
(I bet this isn't measurably faster than the loop though...)
If you wanted to you could extend the suffix array to include "exobyte" and then it would work nicely all the way to int.MaxValue, which is 8.0EB.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 months ago.
Improve this question
I'm designing an answer sheet scorer and currently only have 1 major issue left to deal with and its the answer bubbles. People can fill these in all sorts of ways Filled Answer Bubbles, I have tried using Cv2.HoughCircles() but it doesn't pick up the weird circles and since you have to specific a radius if its too small or too big it wont pick them up Example of HoughCircles attempt. If I was able to at least get all the circles I could probably use Cv2.CountNonZero() after finding the range of white space to consider an answer good/bad. Does anyone have any suggestions I could give a try? Any help is appreciated.
Here's the portion that makes them.
//Gray Image
Mat GrayImage = new Mat();
Cv2.CvtColor(startingImage, GrayImage, ColorConversionCodes.BGR2GRAY);
//Making clear
Mat thresholdImage = new Mat();
Cv2.Threshold(GrayImage, thresholdImage, 100, 255, ThresholdTypes.BinaryInv);
Mat guassianBlurImage = new Mat();
Cv2.GaussianBlur(thresholdImage, guassianBlurImage, new OpenCvSharp.Size(5, 5), 0);
Mat cannyImage = new Mat();
int lower = (int)Math.Max(0, (1.0 - 0.33) * 126);
int upper = (int)Math.Min(255, (1.0 + 0.33) * 126);
Cv2.Canny(guassianBlurImage, cannyImage, lower, upper);
//Finding the Question circles
Mat copy = guassianBlurImage.Clone();
//Image (gray), type, dp, minDist, param1, param2, minRadius, maxRadius
var circles = Cv2.HoughCircles(copy, HoughModes.Gradient, 1, 10, 1, 25, 13, 18);
//Just so we can see the circles
Foreach (var cir in circles)
{
//Debug.Print(cir.Radius.ToString());
Cv2.Circle(startingImage, (int)cir.Center.X, (int)cir.Center.Y, (int)cir.Radius, Scalar.Green, 4);
}
I cleaned up my adobe template which had the circles. They were spaced wrongly so I fixed that. This then got me better images of each singular bubble using my custom method to tile the image.
Below is how I call my method and a small example of what it produces:
List<Mat> questionMats = new List<Mat>();
utils.TileImage(WarpThresholdImage, 3, 8, false, questionMats);
List<Mat> bubbleMats = new List<Mat>();
int n = 0;
foreach (var mat in questionMats)
{
utils.TileImage(mat, 8, 1, false, bubbleMats, "bubble" + n);
n++;
}
After this I am able to determine the min/max of white pixels using Cv2.CountNonZero() kind of jankly by changing the test image with 3 different versions which have empty bubbles, all filled, and ones that are invalid. I used the following code.
//Sample each bubble get nonzero count find min and max for normal versions of filled and unfilled. Filter based on results
int min = 20000;
int max = 0;
/* These represent the test I did to confirm ranges
* lowerNonZeroUnFilled = 849;
* upperNonZeroUnFilled = 1328;
* lowerNonZeroNormalFilled = 643;
* upperNonZeroNormalFilled = 1261;
* lowerNonZeroBadFilled = 602;
* upperNonZeroBadFilled = 2201;
*/
for (int i = 0; i < bubbleMats.Count(); i++)
{
int total = Cv2.CountNonZero(bubbleMats[i]);
//Empty Spaces
if (total == 0) { }
// 600 is the lowest value a filled circle will be
if(total > 600)
{
if(total < min)
{
min = total;
}
if(max < total)
{
max = total;
}
//Cv2.ImShow("Bubble" + i + "-" + total, bubbleMats[i]);
}
}
So this gets me what I want. This probably has issues but I'm confident I can deal with it later on.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I'm writing a SIMD library and trying to squeeze every bit of performance.
I'm already casting in-place the array into a Span<Vector<int>>, instead of creating new objects.
Target arrays are of large size (more than 1000 elements).
Is there a more efficient way of summing an array?
Ideas are welcome.
public static int Sum(int[] array)
{
Vector<int> vSum = Vector<T>.Zero;
int sum;
int i;
Span<Vector<int>> vsArray = MemoryMarshal.Cast<int, Vector<int>>(array);
for (i = 0; i < vsArray.Length; i++)
{
vSum += vsArray[i];
}
sum = Vector.Dot(vSum, Vector<int>.One);
i *= Vector<int>.Count;
for (; i < array.Length; i++)
{
sum += array[i];
}
return sum;
}
Your code is good. Only possible to improve by 4%, here's how:
// Test result: only 4% win on my PC.
[MethodImpl( MethodImplOptions.AggressiveInlining )]
static int sumUnsafeAvx2( int[] array )
{
unsafe
{
fixed( int* sourcePointer = array )
{
int* pointerEnd = sourcePointer + array.Length;
int* pointerEndAligned = sourcePointer + ( array.Length - array.Length % 16 );
Vector256<int> sumLow = Vector256<int>.Zero;
Vector256<int> sumHigh = sumLow;
int* pointer;
for( pointer = sourcePointer; pointer < pointerEndAligned; pointer += 16 )
{
var a = Avx.LoadVector256( pointer );
var b = Avx.LoadVector256( pointer + 8 );
sumLow = Avx2.Add( sumLow, a );
sumHigh = Avx2.Add( sumHigh, b );
}
sumLow = Avx2.Add( sumLow, sumHigh );
Vector128<int> res4 = Sse2.Add( sumLow.GetLower(), sumLow.GetUpper() );
res4 = Sse2.Add( res4, Sse2.Shuffle( res4, 0x4E ) );
res4 = Sse2.Add( res4, Sse2.Shuffle( res4, 1 ) );
int scalar = res4.ToScalar();
for( ; pointer < pointerEnd; pointer++ )
scalar += *pointer;
return scalar;
}
}
}
Here's a complete test.
To be clear, I don’t recommend doing what I wrote above. Not for the 4% improvement. Unsafe code is, well, unsafe. Your version will work without AVX2, and benefits from AVX512 if available, my optimized version gonna crash without AVX2, and won’t use AVX512 even if hardware supports it.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
int arraySum (int [] a, int n)
{
int sum = 0;
n = a.size();
for (int i = 1; i < n; i++)
sum += a[i];
return sum;
}
I want to convert this code from iterative to recursive.
C# Version:
int arraySum ( int [] a, int sum = 0, int i = 0 ) /*i = 0, technically means this code is logically different from yours, however it will count every element and is just a default :)*/
{
if( i < a.Length )
return arraySum( a, sum + a[i], ++i );
return sum;
}
You need:
1- Recursive definition like: sum(n) = n + sum(n-1)
2- You need to specify where should you stop so the recursion does not last forever.
for example: if (n == 0) return 0;
based on this you can code at any language.
C++ Example:
int arraySum (int a[], int n)
{
if(n==1)
return a[n-1];
else
return a[n-1] + arraySum (a, n-1);
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
I have written some code to multiply really long numbers. Was wondering if there are more efficient ways to do this?
Here's how I've done it for now. Basically implemented the typical 'Long multiplication' technique.
internal enum Digit
{
Zero = 0,
One,
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine
}
public class NumbersWhiz
{
public string Add(string Augend, string Addend)
{
string longerNum = (Augend.Length > Addend.Length == true) ? Augend : Addend;
string shorterNum = (Addend.Length < Augend.Length == true) ? Addend : Augend;
int longerLen = (Augend.Length > Addend.Length == true) ? Augend.Length : Addend.Length;
int shorterLen = (Addend.Length < Augend.Length == true) ? Addend.Length : Augend.Length;
//Pad the shorter number initially with zeros to match length of longer number
int deltaLen = longerLen - shorterLen;
string numTwoZeroed = new String('0', deltaLen);
string numTwo = numTwoZeroed.Insert(deltaLen, shorterNum);
string numOne = longerNum;
string result = new String('0', longerLen);
StringBuilder resultBuilder = new StringBuilder(result);
bool carryForward = false;
for (int index = longerLen; index > 0; index--)
{
int augend = Convert.ToInt32(numOne.Substring(index - 1, 1));
int addend = Convert.ToInt32(numTwo.Substring(index - 1, 1));
int sum = (carryForward == true) ? 1 : 0;
sum = sum + augend + addend;
carryForward = ((sum > 9) == true) ? true : false;
int reminder = sum % 10;
resultBuilder[index - 1] = Convert.ToChar(reminder.ToString());
}
if(carryForward)
resultBuilder.Insert(0, '1');
return resultBuilder.ToString();
}
public string Multiply(string Multiplicand, string Multiplier)
{
int resultLen = Multiplicand.Length + Multiplier.Length;
string totalSum = new String('0', resultLen);
for (int index = Multiplier.Length; index > 0; index--)
{
int multiplierDigit = Convert.ToInt32(Multiplier.Substring(index - 1, 1));
string product = Multiply(Multiplicand, (Digit)multiplierDigit);
product += new String('0', Multiplier.Length - index);
totalSum = Add(totalSum, product);
}
return totalSum;
}
string Multiply(string Multiplicand, Digit MultiplierDigit)
{
int multiplier = (int)MultiplierDigit;
if (multiplier == 0)
return "0";
int carry = 0;
bool carryForward = false;
int len = Multiplicand.Length;
int productLen = len + 1;
string result = new String('0', productLen);
StringBuilder resultBuilder = new StringBuilder(result);
for (int index = len; index > 0; index--)
{
int multiplicandDigit = Convert.ToInt32(Multiplicand.Substring(index - 1, 1));
int product = (multiplicandDigit * multiplier) + carry;
carryForward = ((product > 9) == true) ? true : false;
int reminder = product % 10;
carry = (product - reminder) / 10;
resultBuilder[index] = Convert.ToChar(reminder.ToString());
}
if (carryForward)
resultBuilder[0] = Convert.ToChar(carry.ToString());
return resultBuilder.ToString();
}
}
Yes--this is a digit-by-digit operation.
You have a couple of obvious options for doing things faster. One is a binary operation, where you treat one of the numbers as the sum of powers of two, and the result also as the sum of the partial results you get by multiplying by those powers of two.
For example, let's do 17 x 11 (which should give us 181, I believe).
So, let's think of 17 as powers of 2. It's 20 + 24 (i.e., 1 + 16). So we can take 11 * 1 + 11 * 16. We can do each of these multiplications with a shift, so it's 11<<0 + 11<<4.
Another way to look at things (that leads to a somewhat different way of doing things) is useful for large numbers. For the sake of argument, let's assume you can only do 4-bit operations. In this case, you can think of each number in 4-bit pieces and use the distributive property of multiplication to get a result--that is, we take each large number, and break it up into the sum of numbers, each of which represents a "slice" of the bits that make up the whole number. For example, consider something like 0x1234 * 0x4321, and (for the same of simplicity) we'll assume we're going to multiply them with a CPU that can multiply two 8-bit operands to produce a 16-bit result. So, we break each of those up into 8-bit slices:
(0x1200 + 0x34) * (0x4300 + 0x21)
Then we can use the distributive property:
0x1200 * 0x4300 + 0x1200 * 0x21 + 0x34 * 0x4300 + 0x34 * 0x21
Each of these (obviously enough) has only 8 significant bits, so we can carry out each of the operations on our 8-bit CPU. Then you basically just have to take the 4 intermediate results and add them all together. Any reasonable CPU will have a carry bit and an add-with-carry instruction you can use to handle this multiple precision operation.
Although I've shown it with 8-bit operations here, I think it's pretty obvious how this extends to (for example) 256-bit operands on a 32-bit or 64-bit CPU.
Well, yes. There are more advanced multiplication methods.
A quick and easy way to speed up your algorithm a bit is to move from base-10 (aka decimal places) into a number system which is more appropriate for computers. working with 32 bit or 64 bit integers in base-2 will be much faster. You do more work per calculation and also get rid of all the modulo calculations.
Beyond that you could replace the (trivial) multiplication algorithm by something better. If your numbers start to get really large you can get huge speedups by moving into a different complexity region. Your algorithm has complexity O(n*m) where n and m are the number of digits of the two factors.
The Fast Fourier Transform can be used to do huge number multiplications much faster in O(n log n). Worth mentioning is the Number Theoretic Transform which is even more suited for this task.
There is a lot to learn and explore in the topic of large integer arithmetic. If you however just want to multiply numbers and don't care about how it's done I suggest to just use a tested and fast bignum library.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
The community reviewed whether to reopen this question last year and left it closed:
Original close reason(s) were not resolved
Improve this question
Please tell me how can I apply permutation and combination in C# console application and take values of N and r and calculate permutation and combination.
I just had a go doing this for fun, it's actually a little challenging as a naive implementation overflows long very quickly. I've included those in comments.
Equations
nPr = n! / (n - r)!
nCr = n! / r! (n - r)!
Implementaion
public static class PermutationsAndCombinations
{
public static long nCr(int n, int r)
{
// naive: return Factorial(n) / (Factorial(r) * Factorial(n - r));
return nPr(n, r) / Factorial(r);
}
public static long nPr(int n, int r)
{
// naive: return Factorial(n) / Factorial(n - r);
return FactorialDivision(n, n - r);
}
private static long FactorialDivision(int topFactorial, int divisorFactorial)
{
long result = 1;
for (int i = topFactorial; i > divisorFactorial; i--)
result *= i;
return result;
}
private static long Factorial(int i)
{
if (i <= 1)
return 1;
return i * Factorial(i - 1);
}
}
Usage
Console.WriteLine(PermutationsAndCombinations.nPr(10, 3));
Console.WriteLine(PermutationsAndCombinations.nCr(10, 3));
Prints:
720
120