Binary to Decimal Conversion - Formula? - c#

I've been searching a while and haven't gotten anything too useful yet, I'm working on a subnet calculator, and well I have used the decimal to binary which I found here, though, I haven't found a good way to convert binary to decimal.
Note: Remember its FROM binary TO decimal, anyways, im in need of the formula or something like that (meaning calculating it, not the automated one).
What I've understood by reading some other posts that you can somehow get the result by dividing by 10, but I didn't really understand it, so if anyone could point me in the right direction, I'd be glad.
Any and all help is very much appreciated guys! :)

Doing it without LINQ:
var s = "101011"; // my binary "number" as a string
var dec = 0;
for( int i=0; i<s.Length; i++ ) {
// we start with the least significant digit, and work our way to the left
if( s[s.Length-i-1] == '0' ) continue;
dec += (int)Math.Pow( 2, i );
}
A number in any base can be thought of as the sum of its digits multiplied by their place value. For example, the decimal number 3906 can be written as:
3*1000 + 9*100 + 0*10 + 6*1
The place values are simply powers of ten:
3*10^3 + 9*10^2 + 0*10^1 + 6*10^0
(Remember that any number taken to the power of zero is 1.)
Binary works exactly the same way, except the base is 2, not 10. For example, the binary number 101011 can be written as:
1*2^5 + 0*2^4 + 1*2^3 + 0*2^2 + 1*2^1 + 1*2^0
I hope that gives you a better understanding of binary numbers and how to convert them.
On a practical note, the best solution is Matt Grande's; it's always preferable to use a library method instead of rolling your own (unless you have a very good reason to do so).

You can do it like this:
string bin = "10010101010101";
long l = Convert.ToInt64(bin,2);

11010101 = 1*2^7 + 1*2^6 + 0*2^5 + 1*2^4 + 0*2^3 + 1*2^2 + 0*2^1 + 1*2^0
.................= 128 + 64 + 0 + 16 + 0 + 4 + 0 + 1

This works fine
using System;
class BinaryToDecimal
{
static void Main()
{
double sum = 0;
int n = 1111111; // binary number
int strn = n.ToString().Length; //how many digits has my number
for (int i = 0; i < strn; i++)
{
int lastDigit = n % 10; // get the last digit
sum = sum + lastDigit * (Math.Pow(2, i));
n = n / 10; //remove the last digit
}
Console.WriteLine(sum);
}
}

The answer is pretty straightforward. Let's assume you have x as a binary number:
string x = "10010101010101";
Since we know that the general formula to calculate is, starting from right, 2^index_1 + 2^index_2 + 2^index_n
we can use LINQ to do something like (not tested):
x.Reverse()
.Select((element, i) => new { Index = i, Element = char.GetNumericValue(element) })
.Where(a => a.Element != 0)
.Aggregate(0.0, (a, b) => a + (Math.Pow(2, b.Index)));

//a is an integer array which has binary value
sum = 0;
Array.Reverse(a);
for (int j = 0; j < a.Length;j++)
{
if (a[j] == 1)
sum = sum + (Math.Pow(2, j));
}

Here is mine..
private string binary2DecimalCal(string bin)
{
string res;
char[] cArr = bin.ToCharArray();
Array.Reverse(cArr); // Reverse binary string
List<string> sArr = new List<string>();
for (int i = bin.Length - 1; i > -1; i--) // Get the bits
sArr.Add(cArr[i].ToString()+"x2^"+i.ToString()); // Calculation step for each bits
res = String.Join(" + ", sArr.ToArray()); // Join the string with +
return res;
}

Related

How to set mid in binary search?

I was working on this problem 278 First Bad Version on LeetCode. I have used binary search to get the element.
My way of getting middle index of an array m = (start + end)/2 was causing issue in case of large array, closer to MAX_LIMIT of int. First, I thought of int range overflow issue but I am not sure because it worked with end = MAX_LIMIT and some start < MAX_LIMIT even though its going over int range.
I would like to understand how m = start + (end - start)/2 is better than m = (start + end)/2
Code 1 works with input :
2147483647
98765432
But Code 1 fails with input:
2147483647
987654321
I think overflow issue should either happen in both cases or none of them.
1. Code which Worked with m = (start + end)/2 but fails for large array
public int FirstBadVersion(int n) {
if(n == 1){
return 1;
}
int s = 1;
int e = n;
int x = 0;
while(s != e){
x = (s+e)/2;
if(IsBadVersion(x)){
e = x;
}
else{
s = x + 1;
}
}
return s;
}
2. Code which worked with m = start + (end - start)/2
public int FirstBadVersion(int n) {
if(n == 1){
return 1;
}
int s = 1;
int e = n;
int x= 0;
while(s != e){
// x = (s+e)/2;
x = s + (e-s)/2;
if(IsBadVersion(x)){
e = x;
}
else{
s = x + 1;
}
}
return e;
}
You have integer overflow when computing
(a + b) / 2
when (a + b) > int.MaxValue the sum of (a + b) can't be represented as 32 bit integer (it requires 33 bits), and you have incorrect (often negative) result (when bit 33 is ignored) which you then divide by 2.
I suggest working with long in order to be safe from integer overflow:
public int FirstBadVersion(int n) {
// Special case: all versions starting from #1 failed
if (IsBadVersion(1))
return 1;
// let use long in order to avoid integer overflow
long correct = 1;
long failed = n;
// while we have unknown version between correct and failed
while (failed - correct > 1) {
int middle = (low + high) / 2); // it safe now : adding two long values
if (IsBadVersion(middle))
failed = middle;
else
correct = middle;
}
return (int)failed;
}
If using long is cheating and you want to stick to int, you can use the formula below, for int a, b we can put (note that we don't add big values a and b but their halves)
(a + b) / 2 == a / 2 + b / 2 + (a % 2 + b % 2) / 2
Please, note that your formula is not universal
(a + b) = a + (b - a) / 2;
it will work in the particular case of problem #278 where a and b are positive, but will fail in general casw, say when a = 1_000_000_000, b = -2_000_000_000.

Find number on a certain position in array, depending on some rules, added plural to "numbers"

I am a beginner to programming and I am attempting to write a program that should solve the following mathematical problem:
"On a circle we have 108 numbers. The sum of any 20 consecutive numbers is always 1000. At position "1" we have the number 1, at position "19" we have the number 19 and at position "50" we have number 50. What number do we have on position "100"?" The numbers are always integers.
Up to this point i know how to use array and looping structures like "for".
I attempted to set a variable "check" which I initialized it as "false" in order to change it later to true, when I will find the number on position "100".
My initial thought is to go through the array and make the sum of each 20 consecutive numbers. I used two variables in order to assign values for each position that is not 1, 19 or 50 and then make the sum. I did this in two "for" structures, one inside another. Of course, this creates an issue that i am not able to properly calculate the values of the first 20 number.
I checked on the MSDN some information about the "Queue" structure, yet I can't understand how to use it in my particular case.
Let me know please if anyone has some suggestions on how i should handle this.
Thank you.
As you asked, here is the code that I have managed to write so far. Please take into consideration that I am really in the begging of programming and I still have a lot to learn.
check = true;
int[] array = new int[108];
for (counter = 1; counter <= array.Length; counter++)
{
if (counter !=1 || counter !=19 || counter !=50)
{
for (i = 1; i <= 999; i++)
{
array[counter] = i;
if (counter >= 20)
{
for (consecutive = counter; consecutive => 2; consecutive--)
{
checkValue = array[consecutive] + array[consecutive]-1;
}
if (checkvalue != 1000) check = false;
}
}
}
}
As say #fryday the code of this problem doesn't mean anything without logic, so you should understand well the solution before read this.
Let me explain to you the logic of this problem and then read the code (you will see that is quite simple). First you may note that each time you get 20 consecutive numbers, the next number must be equal to the first in the 20 consecutive, because you have
x_1 + x_2 + ... + x_20 = 1000
and
x_2 + ... + x_20 + x_21 = 1000
so
x_1 + x_2 + ... + x_20 = x_2 + ... + x_20 + x_21
and finally
x_1 = x_21
Following this insight all we have to do is walk through the array starting at each one of this positions 1, 19 and 50, fill the positions in the array with this values and then calculate the next position adding 20 to the current and mod by 108, repeat the process until the value in the array is equal to 1, 19 or 50 in each case. Then the values in the array equals to 0 means that all must have the same value (and has not found yet). To found this value sum 20 values consecutive and divide the difference with 1000 by the count of elements with value equal to 0 in such 20 consecutive. You can notice that the position 100 is one of this that have value equals to 0. Finally we get the value of 130.
This is the code:
using System;
namespace Stackoverflow
{
class Program
{
static void Main(string[] args)
{
int[] values = { 1, 19, 50 };
int[] arr = new int[108];
foreach (var val in values)
{
int pos = val - 1;
while (arr[pos] != val)
{
arr[pos] = val;
pos += 20;
pos %= 108;
}
}
int sum = 0;
int zeros = 0;
for (int i = 0; i < 20; i++)
{
if (arr[i] == 0) zeros++;
sum += arr[i];
}
Console.WriteLine((1000 - sum) / zeros);
}
}
}
I solved this problem with array, but better use some type of cycle list. It's about structure choice.
In general you should solve this problem with logic, computer only can help you to check result or visualize data. I'll append code which show how I use array for solving this problem:
N = 108
step = 20
a = [None] * (N + 1)
def toArrayIndex(i):
if i < 0:
return toArrayIndex(N + i)
if i % N == 0:
return N
else:
return i % N
def setKnownNumbers(value, index):
while a[toArrayIndex(index)] != value:
if a[toArrayIndex(index)] != None:
print "ERROR: problem unsolvable i = %d" % toArrayIndex(index)
a[toArrayIndex(index)] = value
index += step
setKnownNumbers(1, 1)
setKnownNumbers(19, 19)
setKnownNumbers(50, 50)
Now you only need to understand how finish it. It's not hard ;)
You can use thi code to output array and check correctness
# output
for i in range(1,N + 1):
print i, a[i]
counter = 0
for i in range(1,N + 1):
s = 0
for j in range(0,step):
s += a[toArrayIndex(i + j)]
if s == 1000:
counter += 1
if counter == N:
print "Correct"
print "a[100] = %d" % a[100]

My algorithm for choosing k element subset to handle huge number in C#

I am writing the algorithm which is choosing a subset (of k elements) from a set (of n elements).
I have accomplished the task with a success. It works fine for small numbers.
I have tested it for n=6, k=3 and n=10, k=5.
The problem is starting now, when I need to use it for huge numbers.
Sometimes I would need to use it for let's say n = 96000000 and k = 3000.
To simply testing a bit, lets focus on example for n = 786432 and k = 1000. Then there is 461946653375201 such a possibilities. As the third parameters to my function there is rank number, so the number for particular unique subset. Let's try few random, for example 3264832 works fine (gave me subset of different numbers), but for 4619466533201 the one number (in subset) is repeated several times, what is wrong. It must be set as well subset based on unique numbers !
Question is to make it works correct and what is the problem ? The numbers are too big even for ulong ?
If you have any question feel free to ask.
Here is my code:
public static ulong BinomialCoefficient(ulong N, ulong K)
{
ulong result = 1;
for (ulong i = 1; i <= K; i++)
{
result *= N - (K - i);
result /= i;
}
return result;
}
public static ulong[] ChooseSubsetByRank(ulong sizeOfSet, ulong sizeOfSubset, ulong rank)
{
ulong[] resultingSubset = new ulong[sizeOfSubset];
ulong x = sizeOfSet;
for (ulong i = sizeOfSubset; i > 0; i--)
{
while (BinomialCoefficient(x, i) > rank)
x--;
resultingSubset[i - 1] = x + 1;
rank = BinomialCoefficient(x + 1, i) - rank - 1;
}
return resultingSubset;
}
And below is the run code. To test it you may change the third argument at the line below.
ulong[] arrayTest = Logic.ChooseSubsetByRank(786432, 1000, 4619466533201);
string test = "";
for (int i = 0; i < arrayTest.Length; i++)
test = test + arrayTest[i].ToString() + " ";
System.Windows.MessageBox.Show(" " + test);
No hope. You can not.
As says spender: use BigInteger.
Your calculation is false (probably if you calculate with ulong which is very very limited for this).
C786432,1000 is in reality :
6033573926325594551531868873570215053708823770889227136141180206574788891075585715726697576999866930083212017993760483485644855730323214507786127283118515758667219335061769573572969492263411636472559059114372691043787225874459276616360823293108500929182830806831624098080982165637186175635880811026388564912224747148201420203796293941118006753515861022396665706095036252893420240334110487119413634294555065166398219767688578556791918697815341165100213662715943043737412038535358818942960435634721564898425752479874494445989953267768476995289375942620219089503401832797819758809124329657724691573254079810257990856068363592549560111914326820802223343980843357174727643299789438961341403866942005159819587812937265119974334351031505150775547311257835039161258554849609865661574816771511161168033768782419369241858323336341530982042093999410402417064838718686064312965836862249598770142918659708106482935266574067985412321680292750817019104479650736141502332606724302400412461373311881584020963297279437835819666355490804970115983436645628460688679416826680621378132834857452816232982148238532837600398378710514758276529410600324271797090502818444825427753513255984828515472462706714900697194261105881768124169338072607942675219899630246822298950117323544399023453603528517829390771915103036173961755955159422806483076370762068538902803552244794986362728794573306025683866038470793703513935653987744702277137020842862116544300481688519625708115843299275718747596961899491910480897148955406962985269341341630460910287516984534632412940751629513018144947978952932944251585462754004392953272268819217751573575925319332190435744062763990089885732157684342450873180307735549083984647582210698121884513785762578827079077499321224628231353083451055184483182777799031632857810808269286112679457384588431986459863394440578400765094557059628627207887510198427517980206661794055812198263391603552022883118047415972254211592143706127815985486692600870607976623561998434373091244295356784708997235625422777415209304056464924341151878262503587256198384142718049855042621519149038523177569828231641690393173865902883254477356340730939905543154540746759842093744184723706019384873683467974667731206411977863548104488741332797192887789005759777716153901423692511142309333333044144404295842596379993363263619514077277847401673508888691303190564956937240904605718333403477875735125913053605250218671009674129773564325959311930556006735185907557691220793718745513911096043358579428288852312401862707347174079157233572972231584221683511928548130771207729971476262436947167805862489722247791944393249804177227081889352572247647101767728277149206844417712380170809760442471306983505977784517425621794122861839031329562074224252476256692950187473655698688314932344304325068076491419731413851641058957149245827761363536463550636030779009703117216843500031930755136735771022162481784531500378393390581558695370099627488825651248884473844195719258621451229987520317542943566297340698028466818937335976792343382788134518740623993664131802576690485505420542865842569675333314900726976825951448445467650748963731221593412649796639395685018463040431779020656159571608044184646177251839940386267422657877801967082672251079906237183824765375906939480520508656199566649638083679757430680818796170362008227564859519761936618260089868694546582873807181452115865272320

Get sum of each digit below n as long

This is the code I have but it's to slow, any way to do it faster..
the number range I'm hitting is 123456789 but I can't get it below 15 seconds, and I need it to get below 5 seconds..
long num = 0;
for (long i = 0; i <= n; i++)
{
num = num + GetSumOfDigits(i);
}
static long GetSumOfDigits(long n)
{
long num2 = 0;
long num3 = n;
long r = 0;
while (num3 != 0)
{
r = num3 % 10;
num3 = num3 / 10;
num2 = num2 + r;
}
return num2;
}
sum =(n(n+1))/2 is not giving me the results I need, not calculating properly..
For N = 12 the sum is 1+2+3+4+5+6+7+8+9+(1+0)+(1+1)+(1+2)= 51.
I need to do this with a formula instead of a loop..
I've got about 15 tests to run through each under 6 seconds..
with parallel I got one test from 15seconds to 4-8 seconds..
Just to show you the test I'm doing this is the hard one..
[Test]
public void When123456789_Then4366712385()
{
Assert.AreEqual(4366712385, TwistedSum.Solution(123456789));
}
On my computer I can run all the tests under 5 seconds..
Look at the photo..
With DineMartine Answer I got these results:
Your algorithm complexity is N log(N). I have found a better algorithm with complexity log(N). The idea is to iterate on the number of digits which is :
log10(n) = ln(n)/ln(10) = O(log(n)).
The demonstration of this algorithm involves a lot of combinatorial calculus. So I choose not to write it here.
Here is the code :
public static long Resolve(long input)
{
var n = (long)Math.Log10(input);
var tenPow = (long)Math.Pow(10, n);
var rest = input;
var result = 0L;
for (; n > 0; n--)
{
var dn = rest / tenPow;
rest = rest - dn * tenPow;
tenPow = tenPow / 10;
result += dn * (rest + 1) + dn * 45 * n * tenPow + dn * (dn-1) * tenPow * 5 ;
}
result += rest * (rest + 1) / 2;
return result;
}
Now you would solve the problem in a fraction of second.
The idea is to write the input as a list of digit :
Assuming the solution is given by a function f, we are looking for g a recursive expression of f over n :
Actually g can be written as follow :
If you find h, the problem would be practically solved.
A little bit convoluted but gets the time down to practicaly zero:
private static long getSumOfSumOfDigitsBelow(long num)
{
if (num == 0)
return 0;
// 1 -> 1 ; 12 -> 10; 123 -> 100; 321 -> 100, ...
int pow10 = (int)Math.Pow(10, Math.Floor(Math.Log10(num)));
long firstDigit = num / pow10;
long sum = 0;
var sum999 = getSumOfSumOfDigitsBelow(pow10 - 1);
var sumRest = getSumOfSumOfDigitsBelow(num % pow10);
sum += (firstDigit - 1)*(firstDigit - 0)/2*pow10 + firstDigit*sum999;
sum += firstDigit*(num%pow10 + 1) + sumRest;
return sum;
}
getSumOfSumOfDigitsBelow(123456789) -> 4366712385 (80us)
getSumOfSumOfDigitsBelow(9223372036854775807) -> 6885105964130132360 (500us - unverified)
The trick is to avoid to compute the same answer again and again. e.g. 33:
your approach:
sum = 1+2+3+4+5+6+7+8+9+(1+0)+(1+1)+(1+2)+ ... +(3+2)+(3+3)
my approach:
sum = 10*(0 + (1+2+3+4+5+6+7+8+9)) +
10*(1 + (1+2+3+4+5+6+7+8+9)) +
10*(2 + (1+2+3+4+5+6+7+8+9)) +
3*(3 + (1 + 2 + 3))
The (1+2+3+4+5+6+7+8+9)-part have to be calculated only once. The loop of 0..firstDigit-1 can be avoided by the n(n-1)/2-trick. I hope this makes sense.
The complexity is O(2^N) with N counting the number of digits. This looks very bad but is fast enough for your threshold of 5s even for long-max. It may be possible to transform this algorithm in something running in O(n) by calling getSumOfSumOfDigitsBelow() only once but it would look much more complex.
First step of optimization: look at your algorithm ;)
Comming back to this problem after the answer of DineMartine :
To further optimize the algorithm, the sum999-part can be replaced by an explicit formula. Lets take some number 9999...9=10^k-1 into the code and replace accordingly:
sum(10^k-1) = (9 - 1)*(9 - 0)/2*pow10 + 9*sum999 + 9*(num%pow10 + 1) + sumRest
sum(10^k-1) = 36*pow10 + 9*sum999 + 9*(num%pow10 + 1) + sumRest
sum999 and sumRest are the same for the numbers of type 10^k:
sum(10^k-1) = 36*pow10 + 10*sum(10^(k-1)-1) + 9*(num%pow10 + 1)
sum(10^k-1) = 36*pow10 + 10*sum(10^(k-1)-1) + 9*((10^k-1)%pow10 + 1)
sum(10^k-1) = 36*pow10 + 10*sum(10^(k-1)-1) + 9*pow10
sum(10^k-1) = 45*pow10 + 10*sum(10^(k-1)-1)
We have a definition of sum(10^k-1) and know sum(9)=45. And we get:
sum(10^k-1) = 45*k*10^k
The updated code:
private static long getSumOfSumOfDigitsBelow(long num)
{
if (num == 0)
return 0;
long N = (int) Math.Floor(Math.Log10(num));
int pow10 = (int)Math.Pow(10, N);
long firstDigit = num / pow10;
long sum = (firstDigit - 1)*firstDigit/2*pow10
+ firstDigit* 45 * N * pow10 / 10
+ firstDigit*(num%pow10 + 1)
+ getSumOfSumOfDigitsBelow(num % pow10);
return sum;
}
This is the same algorithm as the one from DineMartine but expressed in a recursive fashion (I've compared both implementations and yes I'm sure it is ;) ). The runtime goes down to practically zero and the time complexity is O(N) counting the number of digits or O(long(N)) taking the value.
If you have multiple processors (or cores) in your system, you can speed it up quite a lot by doing the calculations in parallel.
The following code demonstrates (it's a compilable console app).
The output when I try it on my system (4 cores with hyperthreading) is as follows for a release build:
x86 version:
Serial took: 00:00:14.6890714
Parallel took: 00:00:03.5324480
Linq took: 00:00:04.4480217
Fast Parallel took: 00:00:01.6371894
x64 version:
Serial took: 00:00:05.1424354
Parallel took: 00:00:00.9860272
Linq took: 00:00:02.6912356
Fast Parallel took: 00:00:00.4154711
Note that the parallel version is around 4 times faster. Also note that the x64 version is MUCH faster (due to the use of long in the calculations).
The code uses Parallel.ForEach along with a Partitioner to split the range of number into sensible regions for the number of processors available. It also uses Interlocked.Add() to quickly add the numbers with efficient locking.
I've also added another method where you need to pre-calculate the sums for the numbers between 0 and 1000. You should only need to pre-calculate the sums once for each run of the program. See FastGetSumOfDigits().
Using FastGetSumOfDigits() more than doubles the previous fastest time on my PC. You can increase the value of SUMS_SIZE to a larger multiple of 10 to increase the speed still further, at the expense of space. Increasing it to 10000 on my PC decreased the time to ~0.3s
(The sums array only needs to be a short array, to save space. It doesn't need a larger type.)
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace Demo
{
internal class Program
{
public static void Main()
{
long n = 123456789;
Stopwatch sw = Stopwatch.StartNew();
long num = 0;
for (long i = 0; i <= n; i++)
num = num + GetSumOfDigits(i);
Console.WriteLine("Serial took: " + sw.Elapsed);
Console.WriteLine(num);
sw.Restart();
num = 0;
var rangePartitioner = Partitioner.Create(0, n + 1);
Parallel.ForEach(rangePartitioner, (range, loopState) =>
{
long subtotal = 0;
for (long i = range.Item1; i < range.Item2; i++)
subtotal += GetSumOfDigits(i);
Interlocked.Add(ref num, subtotal);
});
Console.WriteLine("Parallel took: " + sw.Elapsed);
Console.WriteLine(num);
sw.Restart();
num = Enumerable.Range(1, 123456789).AsParallel().Select(i => GetSumOfDigits(i)).Sum();
Console.WriteLine("Linq took: " + sw.Elapsed);
Console.WriteLine(num);
sw.Restart();
initSums();
num = 0;
Parallel.ForEach(rangePartitioner, (range, loopState) =>
{
long subtotal = 0;
for (long i = range.Item1; i < range.Item2; i++)
subtotal += FastGetSumOfDigits(i);
Interlocked.Add(ref num, subtotal);
});
Console.WriteLine("Fast Parallel took: " + sw.Elapsed);
Console.WriteLine(num);
}
private static void initSums()
{
for (int i = 0; i < SUMS_SIZE; ++i)
sums[i] = (short)GetSumOfDigits(i);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static long GetSumOfDigits(long n)
{
long sum = 0;
while (n != 0)
{
sum += n%10;
n /= 10;
}
return sum;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static long FastGetSumOfDigits(long n)
{
long sum = 0;
while (n != 0)
{
sum += sums[n % SUMS_SIZE];
n /= SUMS_SIZE;
}
return sum;
}
static short[] sums = new short[SUMS_SIZE];
private const int SUMS_SIZE = 1000;
}
}
To increase performance you could calculate the sum starting from the highest number.
Let r=n%10 + 1. Calculate the sum for the last r numbers.
Then we note that if n ends with a 9, then the total sum can be calculated as 10 * sum(n/10) + (n+1)/10 * 45. The first term is the sum of all digits but the last, and the second term is the sum of the last digit.
The function to calculate the total sum becomes:
static long GetSumDigitFrom1toN(long n)
{
long num2 = 0;
long i;
long r = n%10 + 1;
if (n <= 0)
{
return 0;
}
for (i = 0; i < r; i++)
{
num2 += GetSumOfDigits(n - i);
}
// The magic number 45 is the sum of 1 to 9.
return num2 + 10 * GetSumDigitFrom1toN(n/10 - 1) + (n/10) * 45;
}
Test run:
GetSumDigitFrom1toN(12L): 51
GetSumDigitFrom1toN(123456789L): 4366712385
The time complexity is O(log n).
Sum of digits for 0..99999999 is 10000000 * 8 * (0 + 1 + 2 + ... + 9).
Then calculating the rest (100000000..123456789) using the loop might be fast enough.
For N = 12:
Sum of digits for 0..9 is 1 * 1 * 45. Then use your loop for 10, 11, 12.
For N = 123:
Sum of digits for 0..99 is 10 * 2 * 45. Then use your loop for 100..123.
You see the pattern?
A different approach you can try:
Convert the number to a string, then to a Char array
Sum the ASCII codes for all the chars, minus the code for 0
Example code:
long num = 123456789;
var numChars = num.ToString().ToCharArray();
var zeroCode = Convert.ToByte('0');
var sum = numChars.Sum(ch => Convert.ToByte(ch) - zeroCode);

C# Program that converts decimal number to binary

So, I have to make a program that converts a decimal number to binary and prints it, but without using Convert. I got to a point where I can print out the number, but it's in reverse(for example: 12 comes out as 0011 instead of 1100), anyone has an idea how to fix that ? Here's my code:
Console.Write("Number = ");
int n = int.Parse(Console.ReadLine());
string counter = " ";
do
{
if (n % 2 == 0)
{
counter = "0";
}
else if (n % 2 != 0)
{
counter = "1";
}
Console.Write(counter);
n = n / 2;
}
while (n >= 1);
simple solution would be to add them at the beginning:
Console.Write("Number = ");
int n = int.Parse(Console.ReadLine());
string counter = "";
while (n >= 1)
{
counter = (n % 2) + counter;
n = n / 2;
}
Console.Write(counter);
You actually don't even need the if statement
Instead of write them inmediately you may insert them in a StringBuidler
var sb = new StringBuilder();
....
sb.Insert(0, counter);
And then use that StringBuilder
var result = sb.ToString();
You can reverse the String when you finish calculating it
You are generated the digits in the reverse order because you are starting with the least significiant digits when you use % 2 to determine the bit value. What you are doing is not bad though, as it is convenient way to determine the bits. All you have to do is reverse the output by collecting it until you have generated all of the bits then outputing everything in reverse order. ( I did not try to compile and run, may have a typo)
One easy solution is
System.Text.StringBuilder reversi = new System.Text.StringBuilder();
Then in your code replace
Console.Write(counter);
with
reversi.Append(counter);
Finally add the end of your loop, add code like this
string s = reversi.ToString();
for (int ii = s.Length-1; ii >= 0; --ii)
{
Console.Write(s[ii]);
}
There are better ways to do this, but this is easy to understand why it fixes your code -- It looks like you are trying to learn C#.
If I'm not mistaken
int value = 8;
string binary = Convert.ToString(value, 2);

Categories

Resources