inaccurate results with function to add an array of digits together - c#

so i have this function:
static int[] AddArrays(int[] a, int[] b)
{
int length1 = a.Length;
int length2 = b.Length;
int carry = 0;
int max_length = Math.Max(length1, length2) + 1;
int[] minimum_arr = new int[max_length - length1].Concat(a).ToArray();
int[] maximum_arr = new int[max_length - length2].Concat(b).ToArray();
int[] new_arr = new int[max_length];
for (int i = max_length - 1; i >= 0; i--)
{
int first_digit = maximum_arr[i];
int second_digit = i - (max_length - minimum_arr.Length) >= 0 ? minimum_arr[i - (max_length - minimum_arr.Length)] : 0;
if (second_digit + first_digit + carry > 9)
{
new_arr[i] = (second_digit + first_digit + carry) % 10;
carry = 1;
}
else
{
new_arr[i] = second_digit + first_digit + carry;
carry = 0;
}
}
if (carry == 1)
{
int[] result = new int[max_length + 1];
result[0] = 1;
Array.Copy(new_arr, 0, result, 1, max_length);
return result;
}
else
{
return new_arr;
}
}
it basically takes 2 lists of digits and adds them together. the point of this is that each array of digits represent a number that is bigger then the integer limits. now this function is close to working the results get innacurate at certein places and i honestly have no idea why. for example if the function is given these inputs:
"1481298410984109284109481491284901249018490849081048914820948019" and
"3475893498573573849739857349873498739487598" (both of these are being turned into a array of integers before being sent to the function)
the expected output is:
1,481,298,410,984,109,284,112,957,384,783,474,822,868,230,706,430,922,413,560,435,617
and what i get is:
1,481,298,410,984,109,284,457,070,841,142,258,634,158,894,233,092,241,356,043,561,7
i would very much appreciate some help with this ive been trying to figure it out for hours and i cant seem to get it to work perfectly.

I suggest Reverse arrays a and b and use good old school algorithm:
static int[] AddArrays(int[] a, int[] b) {
Array.Reverse(a);
Array.Reverse(b);
int[] result = new int[Math.Max(a.Length, b.Length) + 1];
int carry = 0;
int value = 0;
for (int i = 0; i < Math.Max(a.Length, b.Length); ++i) {
value = (i < a.Length ? a[i] : 0) + (i < b.Length ? b[i] : 0) + carry;
result[i] = value % 10;
carry = value / 10;
}
if (carry > 0)
result[result.Length - 1] = carry;
else
Array.Resize(ref result, result.Length - 1);
// Let's restore a and b
Array.Reverse(a);
Array.Reverse(b);
Array.Reverse(result);
return result;
}
Demo:
string a = "1481298410984109284109481491284901249018490849081048914820948019";
string b = "3475893498573573849739857349873498739487598";
string c = string.Concat(AddArrays(
a.Select(d => d - '0').ToArray(),
b.Select(d => d - '0').ToArray()));
Console.Write(c);
Output:
1481298410984109284112957384783474822868230706430922413560435617

Related

Rounding amount with available set of denominations

This isn't regular rounding thing which rounds up or down based of a single value.
I would want to have a function where I pass the amount as integer and denominations as array of integer.
What that function should return to me is a nearest possible integer value achievable with passed array of denominations.
Whether to round up or down will again be sent as a parameter.
Code:
var amount = 61; // for. e.g.
int[] denoms = [20, 50]; // for. e.g.
bool roundUp = true;
amount = RoundAmount(amount, denoms, roundUp);
Expected result :
RoundAmount function should return me the nearest possible amount achievable with denoms that I have passed.
If roundUp = true, The return value should be 70, because 70 = 20+50
and amount 70 can be achieved by one note of 20s and one note of 50s.
If roundUp = false, It should have returned 60, because 60 =
20+20+20 and amount 60 can be achieved by 3 notes of 20s
What I got so far :
I was only reached to the point where I can manage to round the amount up or down based on a single integer (and not the array of integers)
public int RoundAmount(int amount, int value, bool roundUp)
{
if (roundUp)
amount = amount - (amount % value) + value;
else
amount = amount - (amount % value)
return amount;
}
Edit:
I have another recursive function which checks if amount is achievable or not,
Only if amount isn't achievable, RoundAmount function is called.
So in my example, amount = 70 will never be the input because 70 is achievable with available denoms and I won't call the RoundAmount in that case.
Solution: (Thanks to maraca and Koray)
I'm glad its working with long numbers though it wasn't original requirement.
private static long RoundAmount_maraca(long a, long[] d, bool up)
{
d = d.ToArray();
Array.Sort(d);
if (a < d[0])
return up ? d[0] : 0;
long count = 0;
for (long i = 0; i < d.Length; i++)
{
if (d[i] == 0)
continue;
for (long j = i + 1; j < d.Length; j++)
if (d[j] % d[i] == 0)
d[j] = 0;
if (d[i] > a && !up)
break;
d[count++] = d[i];
if (d[i] > a)
break;
}
if (count == 1)
return (!up ? a : (a + d[0] - 1)) / d[0] * d[0];
long gcd = euclid(d[1], d[0]);
for (long i = 2; i < count && gcd > 1; i++)
gcd = euclid(d[i], gcd);
if (up)
a = (a + gcd - 1) / gcd;
else
a /= gcd;
for (long i = 0; i < count; i++)
{
d[i] /= gcd;
if (a % d[i] == 0)
return a * gcd;
}
var set = new HashSet<long>();
set.Add(0);
long last = 0;
for (long n = d[0]; ; n++)
{
if (!up && n > a)
return last * gcd;
for (long i = 0; i < count && n - d[i] >= 0; i++)
{
if (set.Contains(n - d[i]))
{
if (n >= a)
return n * gcd;
if ((a - n) % d[0] == 0)
return a * gcd;
set.Add(n);
last = n;
break;
}
}
}
}
private static long euclid(long a, long b)
{
while (b != 0)
{
long h = a % b;
a = b;
b = h;
}
return a;
}
I am assuming that you are looking for a performant solution with a relatively small amount of denominations b (e.g. less than 100 denominations). While the amount a and the denominations d[i] can be quite large (e.g. less than 10^6).
Sort d ascending and remove duplicates. When rounding down only keep the values smaller or equal than a and when rounding up keep only the smallest value greater or equal than a and discard the greater ones.
(Optional) remove all numbers which are a multiple of some other number O(b^2).
Calculate the greatest common divisor gcd of the denominations. You can use the Euclidean algorithm starting with the first two numbers then calculate the greatest common divisor of the result and the third number and so on. Of course you can stop as soon as you reach one.
Divide a by gcd, round like you want to round the result (using integer division, rounding down: a /= gcd, rounding up: a = (a + gcd - 1) / gcd).
Divide all denominations by gcd (d[i] /= gcd). Now the greatest common divisor of all denominations is one and therefore it is guaranteed that a Frobenius number exists (all amounts greater than that number can be built and require no rounding). While doing so you can also check if the new value leads to a % d[i] == 0 and immediately return a * gcd if so.
Create a hash set for the values which can be built. It is better than an array because the array is potentially wasting a lot of space (remember the Frobenius number). Add zero to the set.
Create a variable n for the current number, initialize with smallest denomination: n = d[0].
If n can be built with any of the available denominations, in other words the set contains any of n - d[i] then proceed with the next step. Otherwise increase n by one and repeat this step unless n == a and you are rounding down, then you can return the last number that could be built multiplied by gcd immediately. You could also remove n - d[b - 1] from the set each time because this value will not be requested any more.
If n >= a return n * gcd (can only be true when rounding up, rounding down would have returned the result in step 8. already). Else if (a - n) % d[0] == 0 return a * gcd. This check is even better than looking for the Frobenius number (the number after which d[0] - 1 consecutive values can be built), it is more or less the equivalent (d[0] - 1 consecutive values means the difference between one of them and a modulo d[0] has to be zero) but could return much faster. Else increase n by one and continue with step 8.
An example with d = {4, 6} and a = 9999 (or any other big odd number) shows the advantages of this algorithm. It is easy to see that odd numbers can never be built and we would fill up the whole set with all even numbers except 2. But if we divide by gcd we get d = {2, 3} and aUp = 5000 and aDown = 4999. The Frobenius number for {2, 3} is 1 (the only number which cannot be built), so after at most 3 (first number where all modulos are covered) steps (instead of 10000) the modulo would be zero and we would return a * gcd which gives 9998 or 10000 depending on rounding direction, which is the correct result.
Here is the code with test included. I did six runs on my crappy notebook and it took 90, 92, 108, 94, 96 and 101 seconds (edit: early loop escape if current denomination greater than current number && n - d[i] >= 0 halves the times and gives an average of about 45s) for 7200 random roundings (3600 in each direction) with combinations of different amounts of denominations (range 2 to 100), dMax (range 100 to 10^6) and aMax (range 10^4 to 10^6), (see the code at the bottom for the exact values). I think the time for the random number generation and output can be neglected, so with this input and the given ranges the algorithm rounds about 160 numbers per second on average (edit: see thirty times faster version below).
public static final int round(int a, int[] d, boolean up) {
d = d.clone(); // otherwise input gets changed
Arrays.sort(d);
if (a < d[0])
return up ? d[0] : 0;
int count = 0;
for (int i = 0; i < d.length; i++) {
if (d[i] == 0)
continue;
for (int j = i + 1; j < d.length; j++)
if (d[j] % d[i] == 0)
d[j] = 0;
if (d[i] > a && !up)
break;
d[count++] = d[i];
if (d[i] > a)
break;
}
if (count == 1)
return (!up ? a : (a + d[0] - 1)) / d[0] * d[0];
int gcd = euclid(d[1], d[0]);
for (int i = 2; i < count && gcd > 1; i++)
gcd = euclid(d[i], gcd);
if (up)
a = (a + gcd - 1) / gcd;
else
a /= gcd;
for (int i = 0; i < count; i++) {
d[i] /= gcd;
if (a % d[i] == 0)
return a * gcd;
}
Set<Integer> set = new HashSet<>();
set.add(0);
int last = 0;
for (int n = d[0];; n++) {
if (!up && n > a)
return last * gcd;
for (int i = 0; i < count && n - d[i] >= 0; i++) {
if (set.contains(n - d[i])) {
if (n >= a)
return n * gcd;
if ((a - n) % d[0] == 0)
return a * gcd;
set.add(n);
last = n;
break;
}
}
}
}
public static final int euclid(int a, int b) {
while (b != 0) {
int h = a % b;
a = b;
b = h;
}
return a;
}
public static final int REPEAT = 100;
public static final int[] D_COUNT = {2, 5, 10, 20, 50, 100};
public static final int[] D_MAX = {100, 10000, 1000000};
public static final int[] A_MAX = {10000, 1000000};
public static void main(String[] args) {
long start = System.currentTimeMillis();
Random r = new Random();
for (int i = 0; i < REPEAT; i++) {
for (int j = 0; j < D_COUNT.length; j++) {
for (int k = 0; k < D_MAX.length; k++) {
for (int l = 0; l < A_MAX.length; l++) {
int[] d = new int[D_COUNT[j]];
for (int m = 0; m < d.length; m++)
d[m] = r.nextInt(D_MAX[k]);
int a = r.nextInt(A_MAX[l]);
System.out.println(round(a, d, false));
System.out.println(round(a, d, true));
}
}
}
}
System.out.println((System.currentTimeMillis() - start) / 1000 + " seconds");
}
As it turns out #Koray's edit 7 is about three times faster for the given input (only for very large gcds my algorithm above is faster). So to get the ultimate algorithm I replaced the dynamic programming part of my algorithm by that of #Koray (with some improvements). It worked, it is roughly ten times faster than edit 7 and thirty times faster than the algorithm above. Which would give about 5000 roundings per second (very rough estimation) on average.
private static int round(int a, int[] d, boolean up) {
d = d.clone();
Arrays.sort(d);
if (a < d[0])
return up ? d[0] : 0;
int count = 0;
for (int i = 0; i < d.length; i++) {
if (d[i] == 0)
continue;
if (a % d[i] == 0)
return a;
for (int j = i + 1; j < d.length; j++)
if (d[j] > 0 && d[j] % d[i] == 0)
d[j] = 0;
if (d[i] > a && !up)
break;
d[count++] = d[i];
if (d[i] > a)
break;
}
if (count == 1)
return (!up ? a : (a + d[0] - 1)) / d[0] * d[0];
int gcd = euclid(d[1], d[0]);
for (int i = 2; i < count && gcd > 1; i++)
gcd = euclid(d[i], gcd);
if (gcd > 1) {
if (up)
a = (a + gcd - 1) / gcd;
else
a /= gcd;
for (int i = 0; i < count; i++) {
d[i] /= gcd;
if (a % d[i] == 0)
return a * gcd;
}
}
int best = !up ? d[count - 1] : ((a + d[0] - 1) / d[0] * d[0]);
if (d[count - 1] > a) {
if (d[count - 1] < best)
best = d[count - 1];
count--;
}
Stack<Integer> st = new Stack<Integer>();
BitSet ba = new BitSet(a + 1);
for (int i = 0; i < count; i++) {
ba.set(d[i]);
st.push(d[i]);
}
while (st.size() > 0) {
int v1 = st.pop();
for (int i = 0; i < count; i++) {
int val = v1 + d[i];
if (val <= a && !ba.get(val)) {
if ((a - val) % d[0] == 0)
return a * gcd;
ba.set(val, true);
st.push(val);
if (!up && val > best)
best = val;
} else if (val > a) {
if (up && val < best)
best = val;
break;
}
}
}
return best * gcd;
}
private static void test()
{
var amount = 61;
int[] denoms = new int[] { 20, 50 };
int up = RoundAmount(amount, denoms, true);//->70
int down = RoundAmount(amount, denoms, false);//->60
}
private static int RoundAmount(int amount, int[] denoms, bool roundUp)
{
HashSet<int> hs = new HashSet<int>(denoms);
bool added = true;
while (added)
{
added = false;
var arr = hs.ToArray();
foreach (int v1 in arr)
foreach (int v2 in arr)
if ((v1 < amount) && (v2 < amount) && (hs.Add(v1 + v2)))
added = true;
}
int retval = roundUp ? int.MaxValue : int.MinValue;
foreach (int v in hs)
{
if (roundUp)
{
if ((v < retval) && (v >= amount))
retval = v;
}
else
{
if ((v > retval) && (v <= amount))
retval = v;
}
}
return retval;
}
Edit 7
Edit 6 had a bug if a "0" denom exists. I examined #maraca's code in detail (its just great I think) and inspired on that, I've tried some optimizations on my code. Here are the performance comparisons. (I've tried to convert maraca's code to c#, I hope I ve done it right.)
private static int REPEAT = 100;
private static int[] D_COUNT = { 2, 5, 10, 20, 50, 100 };
private static int[] D_MAX = { 100, 10000, 1000000 };
private static int[] A_MAX = { 10000, 1000000 };
private static void testR()
{
Random r = new Random();
long wMaraca = 0;
long wKoray = 0;
for (int i = 0; i < REPEAT; i++)
{
for (int j = 0; j < D_COUNT.Length; j++)
{
for (int k = 0; k < D_MAX.Length; k++)
{
for (int l = 0; l < A_MAX.Length; l++)
{
int[] d = new int[D_COUNT[j]];
for (int m = 0; m < d.Length; m++)
d[m] = r.Next(D_MAX[k]);
int a = r.Next(A_MAX[l]);
Stopwatch maraca = Stopwatch.StartNew();
int m1 = RoundAmount_maraca(a, d, false);
int m2 = RoundAmount_maraca(a, d, true);
maraca.Stop();
wMaraca += maraca.ElapsedMilliseconds;
Stopwatch koray = Stopwatch.StartNew();
int k1 = RoundAmount_koray(a, d, false);
int k2 = RoundAmount_koray(a, d, true);
koray.Stop();
wKoray += koray.ElapsedMilliseconds;
if ((m1 != k1) || (m2 != k2))
{
throw new Exception("something is wrong!");
}
}
}
}
}
//some results with debug compile
//try1
//maraca: 50757 msec
//koray: 19188 msec
//try2
//maraca: 52623 msec
//koray: 19102 msec
//try3
//maraca: 57139 msec
//koray: 18952 msec
//try4
//maraca: 64911 msec
//koray: 21070 msec
}
private static int RoundAmount_koray(int amount, int[] denoms, bool roundUp)
{
List<int> lst = denoms.ToList();
lst.Sort();
if (amount < lst[0])
return roundUp ? lst[0] : 0;
HashSet<int> hs = new HashSet<int>();
for (int i = 0, count = lst.Count; i < count; i++)
{
int v = lst[i];
if (v != 0)
{
if (v > amount && !roundUp)
break;
if (hs.Add(v))
{
if (amount % v == 0)
return amount;
else
for (int j = i + 1; j < count; j++)
if (lst[j] != 0)
if (v % lst[j] == 0)
lst[j] = 0;
else if (amount % (v + lst[j]) == 0)
return amount;
}
}
}
denoms = hs.ToArray();
HashSet<int> hsOK = new HashSet<int>(denoms);
Stack<int> st = new Stack<int>(denoms);
BitArray ba = new BitArray(amount + denoms.Max() * 2 + 1);
int minOK = amount - denoms.Min();
while (st.Count > 0)
{
int v1 = st.Pop();
foreach (int v2 in denoms)
{
int val = v1 + v2;
if (!ba.Get(val))
{
if (amount % val == 0)
return amount;
ba.Set(val, true);
if (val < amount)
st.Push(val);
if (val >= minOK)
hsOK.Add(val);
}
}
}
if (!roundUp)
{
int retval = 0;
foreach (int v in hsOK)
if (v > retval && v <= amount)
retval = v;
return retval;
}
else
{
int retval = int.MaxValue;
foreach (int v in hsOK)
if (v < retval && v >= amount)
retval = v;
return retval;
}
}
private static int RoundAmount_maraca(int a, int[] d, bool up)
{
d = d.ToArray();
Array.Sort(d);
if (a < d[0])
return up ? d[0] : 0;
int count = 0;
for (int i = 0; i < d.Length; i++)
{
if (d[i] == 0)
continue;
for (int j = i + 1; j < d.Length; j++)
if (d[j] % d[i] == 0)
d[j] = 0;
if (d[i] > a && !up)
break;
d[count++] = d[i];
if (d[i] > a)
break;
}
if (count == 1)
return (!up ? a : (a + d[0] - 1)) / d[0] * d[0];
int gcd = euclid(d[1], d[0]);
for (int i = 2; i < count && gcd > 1; i++)
gcd = euclid(d[i], gcd);
if (up)
a = (a + gcd - 1) / gcd;
else
a /= gcd;
for (int i = 0; i < count; i++)
{
d[i] /= gcd;
if (a % d[i] == 0)
return a * gcd;
}
var set = new HashSet<int>();
set.Add(0);
int last = 0;
for (int n = d[0]; ; n++)
{
if (!up && n > a)
return last * gcd;
for (int i = 0; i < count && n - d[i] >= 0; i++)
{
if (set.Contains(n - d[i]))
{
if (n >= a)
return n * gcd;
if ((a - n) % d[0] == 0)
return a * gcd;
set.Add(n);
last = n;
break;
}
}
}
}
private static int euclid(int a, int b)
{
while (b != 0)
{
int h = a % b;
a = b;
b = h;
}
return a;
}
Edit - Maraca in c#
Maraca's last edit clearly outperforms all! I have tried to prepare a better c# conversion of his code + added a ulong version. (int version is ~1.6 times faster than the ulong version)
#region maraca int
private static int RoundAmount_maraca(int a, int[] d0, bool up)
{
int[] d = new int[d0.Length];
Buffer.BlockCopy(d0, 0, d, 0, d.Length * sizeof(int));
Array.Sort(d);
if (a < d[0])
return up ? d[0] : 0;
int count = 0;
for (int i = 0; i < d.Length; i++)
{
if (d[i] == 0)
continue;
for (int j = i + 1; j < d.Length; j++)
if (d[j] % d[i] == 0)
d[j] = 0;
if (d[i] > a && !up)
break;
d[count++] = d[i];
if (d[i] > a)
break;
}
if (count == 1)
return (!up ? a : (a + d[0] - 1)) / d[0] * d[0];
int gcd = euclid(d[1], d[0]);
for (int i = 2; i < count && gcd > 1; i++)
gcd = euclid(d[i], gcd);
if (up)
a = (a + gcd - 1) / gcd;
else
a /= gcd;
for (int i = 0; i < count; i++)
{
d[i] /= gcd;
if (a % d[i] == 0)
return a * gcd;
}
int best = !up ? d[count - 1] : ((a + d[0] - 1) / d[0] * d[0]);
if (d[count - 1] > a)
{
if (d[count - 1] < best)
best = d[count - 1];
count--;
}
var st = new Stack<int>();
BitArray ba = new BitArray(a+1);
for (int i = 0; i < count; i++)
{
ba.Set(d[i], true);
st.Push(d[i]);
}
while (st.Count > 0)
{
int v1 = st.Pop();
for (int i = 0; i < count; i++)
{
int val = v1 + d[i];
if (val <= a && !ba.Get(val))
{
if ((a - val) % d[0] == 0)
return a * gcd;
ba.Set(val, true);
st.Push(val);
if (!up && val > best)
best = val;
}
else if (up && val > a && val < best)
best = val;
}
}
return best * gcd;
}
private static int euclid(int a, int b)
{
while (b != 0)
{
int h = a % b;
a = b;
b = h;
}
return a;
}
#endregion
#region maraca ulong
private static ulong RoundAmount_maraca_ulong(ulong a, ulong[] d0, bool up)
{
ulong[] d = new ulong[d0.Length];
Buffer.BlockCopy(d0, 0, d, 0, d.Length * sizeof(ulong));
Array.Sort(d);
if (a < d[0])
return up ? d[0] : 0ul;
int count = 0;
for (int i = 0; i < d.Length; i++)
{
if (d[i] == 0ul)
continue;
for (int j = i + 1; j < d.Length; j++)
if (d[j] % d[i] == 0ul)
d[j] = 0ul;
if (d[i] > a && !up)
break;
d[count++] = d[i];
if (d[i] > a)
break;
}
if (count == 1)
return (!up ? a : (a + d[0] - 1ul)) / d[0] * d[0];
ulong gcd = euclid(d[1], d[0]);
for (int i = 2; i < count && gcd > 1; i++)
gcd = euclid(d[i], gcd);
if (up)
a = (a + gcd - 1ul) / gcd;
else
a /= gcd;
for (int i = 0; i < count; i++)
{
d[i] /= gcd;
if (a % d[i] == 0ul)
return a * gcd;
}
ulong best = !up ? d[count - 1] : ((a + d[0] - 1ul) / d[0] * d[0]);
if (d[count - 1] > a)
{
if (d[count - 1] < best)
best = d[count - 1];
count--;
}
var st = new Stack<ulong>();
UlongBitArray ba = new UlongBitArray(a + 1ul);
for (int i = 0; i < count; i++)
{
ba.Set(d[i], true);
st.Push(d[i]);
}
while (st.Count > 0)
{
ulong v1 = st.Pop();
for (int i = 0; i < count; i++)
{
ulong val = v1 + d[i];
if (val <= a && !ba.Get(val))
{
if ((a - val) % d[0] == 0ul)
return a * gcd;
ba.Set(val, true);
st.Push(val);
if (!up && val > best)
best = val;
}
else if (up && val > a && val < best)
best = val;
}
}
return best * gcd;
}
private static ulong euclid(ulong a, ulong b)
{
while (b != 0)
{
ulong h = a % b;
a = b;
b = h;
}
return a;
}
class UlongBitArray
{
ulong[] bits;
public UlongBitArray(ulong length)
{
this.bits = new ulong[(length - 1ul) / 32ul + 1ul];
}
public bool Get(ulong index)
{
return (this.bits[index / 32ul] & (1ul << (int)(index % 32ul))) > 0ul;
}
public void Set(ulong index, bool val)
{
if (val)
this.bits[index / 32ul] |= 1ul << (int)(index % 32ul);
else
this.bits[index / 32ul] &= ~(1ul << (int)(index % 32ul));
}
}
#endregion
Edit 8
I have made some improvements and in random tests outperformed #maraca's latest update :) If you choose to use my custom stack class, please make measurements in release mode. (This custom stack class is of course much slower in debug mode but %5-15 faster than .NET's in relase mode. In my tests using the .NET Stack class did not change the performance comparison between two, its just an extra boost.)
private delegate int RoundAmountDelegate(int amount, int[] denoms, bool roundUp);
private static int REPEAT = 100;
private static int[] D_COUNT = { 2, 5, 10, 20, 50, 100 };
private static int[] D_MAX = { 100, 10000, 1000000 };
private static int[] A_MAX = { 10000, 1000000 };
private static void testR()
{
#if DEBUG
while (true)
#endif
{
Random r = new Random();
long wT1 = 0; RoundAmountDelegate func1 = RoundAmount_maraca;
long wT2 = 0; RoundAmountDelegate func2 = RoundAmount_koray;
for (int i = 0; i < REPEAT; i++)
{
for (int j = 0; j < D_COUNT.Length; j++)
{
for (int k = 0; k < D_MAX.Length; k++)
{
for (int l = 0; l < A_MAX.Length; l++)
{
int[] d = new int[D_COUNT[j]];
ulong[] dl = new ulong[D_COUNT[j]];
for (int m = 0; m < d.Length; m++)
{
d[m] = r.Next(D_MAX[k]) + 1;
dl[m] = (ulong)d[m];
}
int a = r.Next(A_MAX[l]);
ulong al = (ulong)a;
Stopwatch w1 = Stopwatch.StartNew();
int m1 = func1(a, d, false);
int m2 = func1(a, d, true);
w1.Stop();
wT1 += w1.ElapsedMilliseconds;
Stopwatch w2 = Stopwatch.StartNew();
int k1 = func2(a, d, false);
int k2 = func2(a, d, true);
w2.Stop();
wT2 += w2.ElapsedMilliseconds;
if ((m1 != k1) || (m2 != k2))
{
#if !DEBUG
MessageBox.Show("error");
#else
throw new Exception("something is wrong!");
#endif
}
}
}
}
}
//some results with release compile
//maraca: 1085 msec
//koray(with .NET Stack<int>): 801 msec
//maraca: 1127 msec
//koray(with .NET Stack<int>): 741 msec
//maraca: 989 msec
//koray(with .NET Stack<int>): 736 msec
//maraca: 962 msec
//koray(with .NET Stack<int>): 632 msec
//-------------------------------------------
//maraca: 1045 msec
//koray(with custom stack): 674 msec
//maraca: 1060 msec
//koray(with custom stack): 606 msec
//maraca: 1175 msec
//koray(with custom stack): 711 msec
//maraca: 878 msec
//koray(with custom stack): 699 msec
#if !DEBUG
MessageBox.Show(wT1 + " " + wT2 + " %" + (double)wT2 / (double)wT1 * 100d);
#endif
}
}
#region Koray
private static int RoundAmount_koray(int amount, int[] denoms, bool roundUp)
{
int[] sorted = new int[denoms.Length];
Buffer.BlockCopy(denoms, 0, sorted, 0, sorted.Length * sizeof(int));
Array.Sort(sorted);
int minD = sorted[0];
if (amount < minD)
return roundUp ? minD : 0;
HashSet<int> hs = new HashSet<int>();
for (int i = 0, count = sorted.Length; i < count; i++)
{
int v = sorted[i];
if (v != 0)
{
if (!roundUp && v > amount)
break;
else if (hs.Add(v))
{
if (amount % v == 0)
return amount;
else
for (int j = i + 1; j < count; j++)
if (sorted[j] != 0)
if (v % sorted[j] == 0)
sorted[j] = 0;
else if (amount % (v + sorted[j]) == 0)
return amount;
}
}
}
denoms = new int[hs.Count];
int k = 0;
foreach (var v in hs)
denoms[k++] = v;
HashSet<int> hsOK = new HashSet<int>(denoms);
stack st = new stack(denoms);
//Stack<int> st = new Stack<int>(denoms);
BitArray ba = new BitArray(amount + denoms[denoms.Length - 1] * 2 + 1);
int minOK = roundUp ? amount : amount - minD;
int maxOK = roundUp ? amount + minD : amount;
while (st.Count > 0)
{
int v1 = st.Pop();
foreach (int v2 in denoms)
{
int val = v1 + v2;
if (val <= maxOK)
{
if (!ba.Get(val))
{
if (amount % val == 0)
return amount;
int diff = amount - val;
if (diff % v1 == 0 || diff % v2 == 0)
return amount;
ba.Set(val, true);
if (val < amount)
st.Push(val);
if (val >= minOK)
hsOK.Add(val);
}
}
else
break;
}
}
if (!roundUp)
{
int retval = 0;
foreach (int v in hsOK)
if (v > retval && v <= amount)
retval = v;
return retval;
}
else
{
int retval = int.MaxValue;
foreach (int v in hsOK)
if (v < retval && v >= amount)
retval = v;
return retval;
}
}
private sealed class stack
{
int[] _array;
public int Count;
public stack()
{
this._array = new int[0];
}
public stack(int[] arr)
{
this.Count = arr.Length;
this._array = new int[this.Count*2];
Buffer.BlockCopy(arr, 0, this._array, 0, this.Count * sizeof(int));
}
public void Push(int item)
{
if (this.Count == this._array.Length)
{
int[] destinationArray = new int[2 * this.Count];
Buffer.BlockCopy(this._array, 0, destinationArray, 0, this.Count * sizeof(int));
this._array = destinationArray;
}
this._array[this.Count++] = item;
}
public int Pop()
{
return this._array[--this.Count];
}
}
#endregion
#region Maraca
private static int RoundAmount_maraca(int a, int[] d0, bool up)
{
int[] d = new int[d0.Length];
Buffer.BlockCopy(d0, 0, d, 0, d.Length * sizeof(int));
Array.Sort(d);
if (a < d[0])
return up ? d[0] : 0;
int count = 0;
for (int i = 0; i < d.Length; i++)
{
if (d[i] == 0)
continue;
for (int j = i + 1; j < d.Length; j++)
if (d[j] % d[i] == 0)
d[j] = 0;
if (d[i] > a && !up)
break;
d[count++] = d[i];
if (d[i] > a)
break;
}
if (count == 1)
return (!up ? a : (a + d[0] - 1)) / d[0] * d[0];
int gcd = euclid(d[1], d[0]);
for (int i = 2; i < count && gcd > 1; i++)
gcd = euclid(d[i], gcd);
if (up)
a = (a + gcd - 1) / gcd;
else
a /= gcd;
for (int i = 0; i < count; i++)
{
d[i] /= gcd;
if (a % d[i] == 0)
return a * gcd;
}
int best = !up ? d[count - 1] : ((a + d[0] - 1) / d[0] * d[0]);
if (d[count - 1] > a)
{
if (d[count - 1] < best)
best = d[count - 1];
count--;
}
var st = new Stack<int>();
BitArray ba = new BitArray(a + 1);
for (int i = 0; i < count; i++)
{
ba.Set(d[i], true);
st.Push(d[i]);
}
while (st.Count > 0)
{
int v1 = st.Pop();
for (int i = 0; i < count; i++)
{
int val = v1 + d[i];
if (val <= a && !ba.Get(val))
{
if ((a - val) % d[0] == 0)
return a * gcd;
ba.Set(val, true);
st.Push(val);
if (!up && val > best)
best = val;
}
else if (up && val > a && val < best)
best = val;
}
}
return best * gcd;
}
private static int euclid(int a, int b)
{
while (b != 0)
{
int h = a % b;
a = b;
b = h;
}
return a;
}
#endregion
This is a standard Knapsack problem and you can google it to refer to its wiki page for its concept.
I think your problem can be splitted to two parts.
Do Knapsack for denominations.
Use f[i] to represent the last denomination used to construct amount i, and f[i]==-1 means that i is not able to get.
fill f with -1
f[0] = 0
for i from 0 to target_amount + min(denoms) - 1
for j from 0 to denoms.size()
if f[i - denoms[j]] != -1
{
f[i] = denoms[j]
break
}
Find nearest amount based on roundUp.
roundUp == true
Starting from target_amount, ascendingly find a f[i] which is not -1.
roundUp == false
Starting from target_amount, descendingly find a f[i] which is not -1.
Optional: find which denominations construct your target amount
Backtrack your f[target_amount].
Just fill array of length amount + smallestdenomination + 1 with possible combinations of coins (standard dynamic programming problem).
Then walk this array from amount index in rounding direction.
Delphi example
var
A : array of Integer;
Denoms: array of Integer;
coin, amount, idx, i, Maxx: Integer;
roundUp: Boolean;
s: string;
begin
amount := 29;
SetLength(Denoms, 2);
Denoms[0] := 7;
Denoms[1] := 13;
Maxx := amount + MinIntValue(Denoms);
SetLength(A, Maxx + 1);
A[0] := 1;
for coin in Denoms do begin
for i := 0 to Maxx - coin do
if A[i] <> 0 then
A[i + coin] := coin;
end;
roundUp := True;
idx := amount;
i := 2 * Ord(roundUp) - 1;// 1 for roundUp=true, -1 for false
while A[idx] = 0 do //scan for nonzero entry
idx := idx + i;
s := '';
while idx > 0 do begin //roll back to get components of this sum
s := s + Format('%d ', [A[idx]]);
idx := idx - A[idx];
end;
Memo1.Lines.Add(s);
outputs 13 13 7 combination for roundUp := True; and 7 7 7 7 otherwise.
(Code does not seek for "optimal" solution)
Example for coins 3 and 5:
[0, 0, 0, 3, 0, 5, 3, 0, 5, 3, 5]
To find what coins make cell 8, step down by cell value:by 5 then by 3.
The Coin Problem is a well-researched topic and I would like to reference some papers where you can probably find better solutions:
The Money Changing Problem Revisited
Coin Problem
Also, using C# (statically typed language) will restrict you from having the most efficient algorithm over a dynamically typed language. If you plan to go down that route, you can have a look at this website The Frobenius problem. You can right click and inspect the code (though I really didn't understand much having no experience of javascript)
Anyhow, this is how I would tackle the problem in C#:
private static List<int> _denominations = new List<int>() { 1000, 5000 };
private static int _denominationMin = _denominations[0];
static void Main()
{
bool roundDown = false;
Console.WriteLine("Enter number: ");
int input = Convert.ToInt32(Console.ReadLine());
if(roundDown)
{
for(int i = input; i > _denominationMin; i--)
{
if(Check(0,0,i))
{
Console.WriteLine("Number: {0}", i);
break;
}
}
}
else
{
for (int i = input; i < int.MaxValue; i++)
{
if (Check(0, 0, i))
{
Console.WriteLine("Number: {0}", i);
break;
}
}
}
Console.Read();
}
static bool Check(int highest, int sum, int goal)
{
//Bingo!
if (sum == goal)
{
return true;
}
//Oops! exceeded here
if (sum > goal)
{
return false;
}
// Loop through _denominations.
foreach (int value in _denominations)
{
// Add higher or equal amounts.
if (value >= highest)
{
if(Check(value, sum + value, goal))
{
return true;
}
}
}
return false;
}
Worked well with {4,6} for input 19999, so I don't think it is all that bad. Surely has scope for improvements for not running into Stackoverflow Exception. One could half the input or quarter it. Or subtract a number that has factors whose subset are the denominations. Also, important to have the denominations sorted and contain no multiples of another entry E.x. {4, 6, 8} -> {4, 6}.
Anyhow, if I have time I will try to make it more efficient. Just wanted to provide an alternate solution.

Sum of large numbers represented as arrays?

The numbers are stored in the arrays with their digits in reverse order. Here is a functions that should add two numbers, a and b, and store the sum in result:
public static void SumDigitArraysDifferentSize(int[] a, int[] b, int[] result)
{
int length = Math.Max(a.Length, b.Length);
for (int i = 0; i < length; i++)
{
int lhs = (i < a.Length) ? a[i] : 0;
int rhs = (i < b.Length) ? b[i] : 0;
result[i] = (result[i] + lhs + rhs) % 10;
int carry = (result[i] + lhs + rhs) / 10;
for (int j = 1; carry > 0; j++)
{
result[i + j] = (result[i + j] + carry) % 10;
carry = (result[i + j] + carry) / 10;
}
}
}
However, if I add for example:
static void Main(string[] args)
{
int[] lhs = { 9 }
int[] rhs = { 9, 9 };
int size = Math.Max(lhs.Length, rhs.Length) + 1;
int[] result = new int[size];
SumDigitArraysDifferentSize(lhs, rhs, result);
PrintArray(result);
}
the result is:
{ 8, 1, 1 }
instead of the expected:
{ 8, 0, 1 }
What am I doing wrong?
For the MCVE:
public static void PrintArray(int[] Array)
{
Console.Write("{");
int length = Array.Length;
for (int i = 0; i < length; i++)
{
Console.Write(Array[i]);
if (i < length - 1)
{
Console.Write(", ");
}
}
Console.Write("}\n");
}
You are assigning result[i], and using the result again in the calculation of the carry.
This:
result[i] = (result[i] + lhs + rhs) % 10;
int carry = (result[i] + lhs + rhs) / 10;
Should be:
var sum = result[i] + lhs + rhs;
result[i] = (sum) % 10;
int carry = (sum) / 10;
And the same for the calculation in the for (int j = 1; ...).
For the sake of completeness, here is the result of the proposed (by #Lasse V. Karlsen) implementation from the comment section
public static void SumDigitArrays(int[] a, int[] b, int[] result)
{
int length = Math.Max(a.Length, b.Length);
for (int i = 0; i < length; i++)
{
int lhs = (i < a.Length) ? a[i] : 0;
int rhs = (i < b.Length) ? b[i] : 0;
int sum = result[i] + lhs + rhs;
result[i] = sum % 10;
int carry = sum / 10;
result[i + 1] = result[i + 1] + carry;
}
}

Reorder digits in integer using C#

I want to ask how I can reorder the digits in an Int32 so they result in the biggest possible number.
Here is an example which visualizes what I am trying to do:
2927466 -> 9766422
12492771 -> 97742211
I want to perform the ordering of the digits without using the System.Linq namespace and without converting the integer into a string value.
This is what I got so far:
public static int ReorderInt32Digits(int v)
{
int n = Math.Abs(v);
int l = ((int)Math.Log10(n > 0 ? n : 1)) + 1;
int[] d = new int[l];
for (int i = 0; i < l; i++)
{
d[(l - i) - 1] = n % 10;
n /= 10;
}
if (v < 0)
d[0] *= -1;
Array.Sort(d);
Array.Reverse(d);
int h = 0;
for (int i = 0; i < d.Length; i++)
{
int index = d.Length - i - 1;
h += ((int)Math.Pow(10, index)) * d[i];
}
return h;
}
This algorithm works flawlessly but I think it is not very efficient.
I would like to know if there is a way to do the same thing more efficiently and how I could improve my algorithm.
You can use this code:
var digit = 2927466;
String.Join("", digit.ToString().ToCharArray().OrderBy(x => x));
Or
var res = String.Join("", digit.ToString().ToCharArray().OrderByDescending(x => x) );
Not that my answer may or may not be more "efficient", but when I read your code you calculated how many digits there are in your number so you can determine how large to make your array, and then you calculated how to turn your array back into a sorted integer.
It would seem to me that you would want to write your own code that did the sorting part without using built in functionality, which is what my sample does. Plus, I've added the ability to sort in ascending or descending order, which is easy to add in your code too.
UPDATED
The original algorithm sorted the digits, now it sorts the digits so that the end result is the largest or smallest depending on the second parameter passed in. However, when dealing with a negative number the second parameter is treated as opposite.
using System;
public class Program
{
public static void Main()
{
int number1 = 2927466;
int number2 = 12492771;
int number3 = -39284925;
Console.WriteLine(OrderDigits(number1, false));
Console.WriteLine(OrderDigits(number2, true));
Console.WriteLine(OrderDigits(number3, false));
}
private static int OrderDigits(int number, bool asc)
{
// Extract each digit into an array
int[] digits = new int[(int)Math.Floor(Math.Log10(Math.Abs(number)) + 1)];
for (int i = 0; i < digits.Length; i++)
{
digits[i] = number % 10;
number /= 10;
}
// Order the digits
for (int i = 0; i < digits.Length; i++)
{
for (int j = i + 1; j < digits.Length; j++)
{
if ((!asc && digits[j] > digits[i]) ||
(asc && digits[j] < digits[i]))
{
int temp = digits[i];
digits[i] = digits[j];
digits[j] = temp;
}
}
}
// Turn the array of digits back into an integer
int result = 0;
for (int i = digits.Length - 1; i >= 0; i--)
{
result += digits[i] * (int)Math.Pow(10, digits.Length - 1 - i);
}
return result;
}
}
Results:
9766422
11224779
-22345899
See working example here... https://dotnetfiddle.net/RWA4XV
public static int ReorderInt32Digits(int v)
{
var nums = Math.Abs(v).ToString().ToCharArray();
Array.Sort(nums);
bool neg = (v < 0);
if(!neg)
{
Array.Reverse(nums);
}
return int.Parse(new string(nums)) * (neg ? -1 : 1);
}
This code fragment below extracts the digits from variable v. You can modify it to store the digits in an array and sort/reverse.
int v = 2345;
while (v > 0) {
int digit = v % 10;
v = v / 10;
Console.WriteLine(digit);
}
You can use similar logic to reconstruct the number from (sorted) digits: Multiply by 10 and add next digit.
I'm posting this second answer because I think I got the most efficient algorithm of all (thanks for the help Atul) :)
void Main()
{
Console.WriteLine (ReorderInt32Digits2(2927466));
Console.WriteLine (ReorderInt32Digits2(12492771));
Console.WriteLine (ReorderInt32Digits2(-1024));
}
public static int ReorderInt32Digits2(int v)
{
bool neg = (v < 0);
int mult = neg ? -1 : 1;
int result = 0;
var counts = GetDigitCounts(v);
for (int i = 0; i < 10; i++)
{
int idx = neg ? 9 - i : i;
for (int j = 0; j < counts[idx]; j++)
{
result += idx * mult;
mult *= 10;
}
}
return result;
}
// From Atul Sikaria's answer
public static int[] GetDigitCounts(int n)
{
int v = Math.Abs(n);
var result = new int[10];
while (v > 0) {
int digit = v % 10;
v = v / 10;
result[digit]++;
}
return result;
}

Compare string similarity

What is the best way to compare two strings to see how similar they are?
Examples:
My String
My String With Extra Words
Or
My String
My Slightly Different String
What I am looking for is to determine how similar the first and second string in each pair is. I would like to score the comparison and if the strings are similar enough, I would consider them a matching pair.
Is there a good way to do this in C#?
static class LevenshteinDistance
{
public static int Compute(string s, string t)
{
if (string.IsNullOrEmpty(s))
{
if (string.IsNullOrEmpty(t))
return 0;
return t.Length;
}
if (string.IsNullOrEmpty(t))
{
return s.Length;
}
int n = s.Length;
int m = t.Length;
int[,] d = new int[n + 1, m + 1];
// initialize the top and right of the table to 0, 1, 2, ...
for (int i = 0; i <= n; d[i, 0] = i++);
for (int j = 1; j <= m; d[0, j] = j++);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;
int min1 = d[i - 1, j] + 1;
int min2 = d[i, j - 1] + 1;
int min3 = d[i - 1, j - 1] + cost;
d[i, j] = Math.Min(Math.Min(min1, min2), min3);
}
}
return d[n, m];
}
}
If anyone was wondering what the C# equivalent of what #FrankSchwieterman posted is:
public static int GetDamerauLevenshteinDistance(string s, string t)
{
if (string.IsNullOrEmpty(s))
{
throw new ArgumentNullException(s, "String Cannot Be Null Or Empty");
}
if (string.IsNullOrEmpty(t))
{
throw new ArgumentNullException(t, "String Cannot Be Null Or Empty");
}
int n = s.Length; // length of s
int m = t.Length; // length of t
if (n == 0)
{
return m;
}
if (m == 0)
{
return n;
}
int[] p = new int[n + 1]; //'previous' cost array, horizontally
int[] d = new int[n + 1]; // cost array, horizontally
// indexes into strings s and t
int i; // iterates through s
int j; // iterates through t
for (i = 0; i <= n; i++)
{
p[i] = i;
}
for (j = 1; j <= m; j++)
{
char tJ = t[j - 1]; // jth character of t
d[0] = j;
for (i = 1; i <= n; i++)
{
int cost = s[i - 1] == tJ ? 0 : 1; // cost
// minimum of cell to the left+1, to the top+1, diagonally left and up +cost
d[i] = Math.Min(Math.Min(d[i - 1] + 1, p[i] + 1), p[i - 1] + cost);
}
// copy current distance counts to 'previous row' distance counts
int[] dPlaceholder = p; //placeholder to assist in swapping p and d
p = d;
d = dPlaceholder;
}
// our last action in the above loop was to switch d and p, so p now
// actually has the most recent cost counts
return p[n];
}
I am comparing two sentences like this
string[] vs = string1.Split(new char[] { ' ', '-', '/', '(', ')' },StringSplitOptions.RemoveEmptyEntries);
string[] vs1 = string2.Split(new char[] { ' ', '-', '/', '(', ')' }, StringSplitOptions.RemoveEmptyEntries);
vs.Intersect(vs1, StringComparer.OrdinalIgnoreCase).Count();
Intersect gives you a set of identical word lists , I continue by looking at the count and saying if it is more than 1, these two sentences contain similar words.

Integer to Integer Array C# [duplicate]

This question already has answers here:
Is there an easy way to turn an int into an array of ints of each digit?
(11 answers)
Closed 1 year ago.
I had to split an int "123456" each value of it to an Int[] and i have already a Solution but i dont know is there any better way :
My solution was :
public static int[] intToArray(int num){
String holder = num.ToString();
int[] numbers = new int[Holder.ToString().Length];
for(int i=0;i<numbers.length;i++){
numbers[i] = Convert.toInt32(holder.CharAt(i));
}
return numbers;
}
A simple solution using LINQ
int[] result = yourInt.ToString().Select(o=> Convert.ToInt32(o) - 48 ).ToArray()
I believe this will be better than converting back and forth. As opposed to JBSnorro´s answer I reverse after converting to an array and therefore avoid IEnumerable´s which I think will contribute to a little bit faster code. This method work for non negative numbers, so 0 will return new int[1] { 0 }.
If it should work for negative numbers, you could do a n = Math.Abs(n) but I don't think that makes sense.
Furthermore, if it should be more performant, I could create the final array to begin with by making a binary-search like combination of if-statements to determine the number of digits.
public static int[] digitArr(int n)
{
if (n == 0) return new int[1] { 0 };
var digits = new List<int>();
for (; n != 0; n /= 10)
digits.Add(n % 10);
var arr = digits.ToArray();
Array.Reverse(arr);
return arr;
}
Update 2018:
public static int numDigits(int n) {
if (n < 0) {
n = (n == Int32.MinValue) ? Int32.MaxValue : -n;
}
if (n < 10) return 1;
if (n < 100) return 2;
if (n < 1000) return 3;
if (n < 10000) return 4;
if (n < 100000) return 5;
if (n < 1000000) return 6;
if (n < 10000000) return 7;
if (n < 100000000) return 8;
if (n < 1000000000) return 9;
return 10;
}
public static int[] digitArr2(int n)
{
var result = new int[numDigits(n)];
for (int i = result.Length - 1; i >= 0; i--) {
result[i] = n % 10;
n /= 10;
}
return result;
}
int[] outarry = Array.ConvertAll(num.ToString().ToArray(), x=>(int)x);
but if you want to convert it to 1,2,3,4,5:
int[] outarry = Array.ConvertAll(num.ToString().ToArray(), x=>(int)x - 48);
I'd do it like this:
var result = new List<int>();
while (num != 0) {
result.Insert(0, num % 10);
num = num / 10;
}
return result.ToArray();
Slightly less performant but possibly more elegant is:
return num.ToString().Select(c => Convert.ToInt32(c.ToString())).ToArray();
Note that these both return 1,2,3,4,5,6 rather than 49,50,51,52,53,54 (i.e. the byte codes for the characters '1','2','3','4','5','6') as your code does. I assume this is the actual intent?
Using conversion from int to string and back probably isn't that fast. I would use the following
public static int[] ToDigitArray(int i)
{
List<int> result = new List<int>();
while (i != 0)
{
result.Add(i % 10);
i /= 10;
}
return result.Reverse().ToArray();
}
I do have to note that this only works for strictly positive integers.
EDIT:
I came up with an alternative. If performance really is an issue, this will probably be faster, although you can only be sure by checking it yourself for your specific usage and application.
public static int[] ToDigitArray(int n)
{
int[] result = new int[GetDigitArrayLength(n)];
for (int i = 0; i < result.Length; i++)
{
result[result.Length - i - 1] = n % 10;
n /= 10;
}
return result;
}
private static int GetDigitArrayLength(int n)
{
if (n == 0)
return 1;
return 1 + (int)Math.Log10(n);
}
This works when n is nonnegative.
Thanks to ASCII character table. The simple answer using LINQ above yields answer + 48.
Either
int[] result = youtInt.ToString().Select(o => Convert.ToInt32(o) - 48).ToArray();
or
int[] result = youtInt.ToString().Select(o => int.Parse(o.ToString())).ToArray();
can be used
You can do that without converting it to a string and back:
public static int[] intToArray(int num) {
List<int> numbers = new List<int>();
do {
numbers.Insert(0, num % 10);
num /= 10;
} while (num > 0);
return numbers.ToArray();
}
It only works for positive values, of course, but your original code also have that limitation.
I would convert it in the below manner
if (num == 0) return new int[1] { 0 };
var digits = new List<int>();
while (num > 0)
{
digits.Add(num % 10);
num /= 10;
}
var arr = digits.ToArray().Reverse().ToArray();
string DecimalToBase(int iDec, int numbase)
{
string strBin = "";
int[] result = new int[32];
int MaxBit = 32;
for(; iDec > 0; iDec/=numbase)
{
int rem = iDec % numbase;
result[--MaxBit] = rem;
}
for (int i=0;i<result.Length;i++)
if ((int)result.GetValue(i) >= base10)
strBin += cHexa[(int)result.GetValue(i)%base10];
else
strBin += result.GetValue(i);
strBin = strBin.TrimStart(new char[] {'0'});
return strBin;
}
int BaseToDecimal(string sBase, int numbase)
{
int dec = 0;
int b;
int iProduct=1;
string sHexa = "";
if (numbase > base10)
for (int i=0;i<cHexa.Length;i++)
sHexa += cHexa.GetValue(i).ToString();
for(int i=sBase.Length-1; i>=0; i--,iProduct *= numbase)
{
string sValue = sBase[i].ToString();
if (sValue.IndexOfAny(cHexa) >=0)
b=iHexaNumeric[sHexa.IndexOf(sBase[i])];
else
b= (int) sBase[i] - asciiDiff;
dec += (b * iProduct);
}
return dec;
}
i had similar requirement .. i took from many good ideas, and added a couple missing pieces .. where many folks weren’t handling zero or negative values. this is what i came up with:
public static int[] DigitsFromInteger(int n)
{
int _n = Math.Abs(n);
int length = ((int)Math.Log10(_n > 0 ? _n : 1)) + 1;
int[] digits = new int[length];
for (int i = 0; i < length; i++)
{
digits[(length - i) - 1] = _n % 10 * ((i == (length - 1) && n < 0) ? -1 : 1);
_n /= 10;
}
return digits;
}
i think this is pretty clean .. although, it is true we're doing a conditional check and several extraneous calculations with each iteration .. while i think they’re nominal in this case, you could optimize a step further this way:
public static int[] DigitsFromInteger(int n)
{
int _n = Math.Abs(n);
int length = ((int)Math.Log10(_n > 0 ? _n : 1)) + 1;
int[] digits = new int[length];
for (int i = 0; i < length; i++)
{
//digits[(length - i) - 1] = _n % 10 * ((i == (length - 1) && n < 0) ? -1 : 1);
digits[(length - i) - 1] = _n % 10;
_n /= 10;
}
if (n < 0)
digits[0] *= -1;
return digits;
}
A slightly more concise way to do MarkXA's one-line version:
int[] result = n.ToString().Select(c => (int)Char.GetNumericValue(c)).ToArray();
GetNumericValue returns the visible number in your char as a double, so if your string is "12345", it will return the doubles 1,2,3,4,5, which can each be cast to an int. Note that using Convert.ToInt32 on a char in C# returns the ASCII code, so you would get 49,50,51,52,53. This can understandably lead to a mistake.
Here is a Good Solution for Convert Your Integer into Array i.e:
int a= 5478 into int[]
There is no issue if You Have a String and You want to convert a String into integer Array for example
string str=4561; //Convert into
array[0]=4;
array[1]=5;
array[2]=6;
array[3]=7;
Note: The Number of zero (0) in devider are Equal to the Length of input and Set Your Array Length According to Your input length
Now Check the Coding:
string str=4587;
int value = Convert.ToInt32(str);
int[] arr = new int[4];
int devider = 10000;
for (int i = 0; i < str.Length; i++)
{
int m = 0;
devider /= 10;
arr[i] = value / devider;
m = value / devider;
value -= (m * devider);
}
private static int[] ConvertIntToArray(int variable)
{
string converter = "" + variable;
int[] convertedArray = new int[converter.Length];
for (int i=0; i < convertedArray.Length;i++) //it can be also converter.Length
{
convertedArray[i] = int.Parse(converter.Substring(i, 1));
}
return convertedArray;
}
We get int via using method. Then, convert it to string immediately (123456->"123456"). We have a string called converter and carry to int value. Our string have a string.Length, especially same length of int so, we create an array called convertedArray that we have the length, that is converter(string) length. Then, we get in the loop where we are convert the string to int one by one via using string.Substring(i,1), and assign the value convertedArray[i]. Then, return the convertedArray.At the main or any method you can easily call the method.
public static int[] intToArray(int num)
{
num = Math.Abs(num);
int length = num.ToString().Length;
int[] arr = new int[length];
do
{
arr[--length] = num % 10;
num /= 10;
} while (num != 0);
return arr;
}
Dividing by system base (decimal in this case) removes the right most digit, and we get that digit by remainder operator. We keep repeating until we end up with a zero. Each time a digit is removed it will be stored in an array starting from the end of the array and backward to avoid the need of revering the array at the end. The Math.Abs() function is to handle the negative input, also the array is instantiated with the same size as input length.
Integer or Long to Integer Array C#
Convert it to char array and subtract 48.
public static int[] IntToArray(int value, int length)
{
char[] charArray = new char[length];
charArray = value.ToString().ToCharArray();
int[] intArray = new int[length];
for (int i = 0; i < intArray.Length; i++)
{
intArray[i] = charArray[i] - 48;
}
return intArray;
}
public static int[] LongToIntArray(long value, int length)
{
char[] charArray = new char[length];
charArray = value.ToString().ToCharArray();
int[] intArray = new int[length];
for (int i = 0; i < intArray.Length; i++)
{
intArray[i] = charArray[i] - 48;
}
return intArray;
}

Categories