Finding number of digits of a number in C# - c#

I'm trying to write a piece of code in C# to find the number digits of a integer number, the code works perfectly for all numbers (negative and positive) but I have problem with 10, 100,1000 and so on, it shows one less digits than the numbers' actual number of digits. like 1 for 10 and 2 for 100..
long i = 0;
double n;
Console.Write("N? ");
n = Convert.ToInt64(Console.ReadLine());
do
{
n = n / 10;
i++;
}
while(Math.Abs(n) > 1);
Console.WriteLine(i);

Your while condition is Math.Abs(n) > 1, but in the case of 10, you are only greater than 1 the first time. You could change this check to be >=1 and that should fix your problem.
do
{
n = n / 10;
i++;
}
while(Math.Abs(n) >= 1);

Use char.IsDigit:
string input = Console.ReadLine();
int numOfDigits = input.Count(char.IsDigit);

What's wrong with:
Math.Abs(n).ToString(NumberFormatInfo.InvariantInfo).Length;
Indeed, converting a number to a string is computationally expensive compared to some arithmetic, but it is hard to deal with negative nubers, overflow,...
You need to use Math.Abs to make sure the sign is not counted, and it is a safe option to use NumberFormatInfo.InvariantInfo so that for instance certain cultures that use spaces and accents, do not alter the behavior.

public static int NumDigits(int value, double #base)
{
if(#base == 1 || #base <= 0 || value == 0)
{
throw new Exception();
}
double rawlog = Math.Log(Math.Abs(value), #base);
return rawlog - (rawlog % 1);
}
This NumDigits function is designed to find the number of digits for a value in any base. It also includes error handling for invalid input. The # with the base variable is to make it a verbatim variable (because base is a keyword).

Console.ReadLine().Replace(",", String.Empty).Length;

this will count all the char in a string
int amount = 0;
string input = Console.ReadLine();
char[] chars = input.ToArray();
foreach (char c in chars)
{
amount++;
}
Console.WriteLine(amount.ToString());
Console.ReadKey();

Related

How to write a toString method without using other class libraries [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I want to write my own toString method since I am not allowed to use any class libraries.
So I took a look into the source code of the toString method, but it uses a lot of other libraries. I want to convert an Integer into a String, but I am not sure how i can address the numbers one by one.
If I could do that, I could continue by casting the Integers into a Char and in the end add up all the Chars for a String.
Can someone help?
Here's a similar approach to the other answers.
The important points:
We calculate the last digit of a number by finding its remainder when it's divided by 10 (i.e. lastDigit = number % 10;)
To throw away the last digit of a number, simply divide it by 10.
When finding digits that way, they will of course be returned in reverse order (least significant digit first) so you have to reverse the digits to get the correct answer. One way to do this is to store from the end to the beginning of a char array.
Negative numbers have to be handled specially. The easiest way is to note that the number is negative so that a - sign can be added when appropriate; then, negate the number to make it positive. However, note that you can't negate int.MinValue, so that has to be handled specially.
You can convert from a numeric digit to its char equivalent by adding it to the char '0' and casting the result back to char.
Here's an approach that uses those points:
public static string MyToString(int number)
{
if (number == int.MinValue)
return "-2147483648"; // Special case.
char[] digits = new char[64]; // Support at most 64 digits.
int last = digits.Length;
bool isNegative = number < 0;
if (isNegative)
number = -number;
do
{
digits[--last] = (char) ('0' + number % 10);
number /= 10;
}
while (number != 0);
if (isNegative)
digits[--last] = '-';
return new string(digits, last, digits.Length-last);
}
I think the main part you were asking about is how to get the digits of a number one-by-one, which is answered by the do/while loop above.
[EDIT] Addressed the points raised in the comments below.
I don't understand why you're not allowed to use any libraries. But if you need to do the conversion entirely by hand, you could do it something like this
private static string IntToString(int i)
{
string[] digits = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
string sign = (i < 0 ? "-" : "");
var absI = (i < 0 ? -i : i);
string result = "";
while (absI != 0)
{
int digit = absI % 10;
result = digits[digit] + result;
absI = (absI - digit) / 10;
}
return sign + result;
}
The code above doesn't work properly for zero. If you need that, it's very simple to add.
For example you can split your number into individual characters:
// Note that this is just for example and for positive numbers only.
IEnumerable<char> ToChar(int num)
{
while (num > 0)
{
// adding '0' to number will return char for that number
char ch = (char)(num % 10 + '0');
num /= 10;
yield return ch;
}
}
then create new string based on that:
string ToString(int num)
{
// ToChar will return char collection in reverse order,
// so you will need to reverse collection before using.
// Well in your situation you will be probably needed to
// to write Reverse method by yourself, so this is just for
// working example
var chArray = ToChar(num).Reverse().ToArray();
string str = new string(chArray);
return str;
}
and usage:
int i = 554;
string str = ToString(i);
References: DotNetFiddle Example (with simplified ToChar() method)

How to take digits from two different numbers and form a new one

I have the following problem here:My input is several lines of 2 digit numbers and I need to make a new number using the second digit of the first number and the first of the next one.
Example:
int linesOfNumbers = Convert.ToInt32(Console.ReadLine());
for(int i = 0,i<linesOfNumbers,i++)
{
int numbers = Conver.ToInt32(Console.ReadLine());
//that's for reading the input
}
I know how to separate the numbers into digits.My question is how to merge them.
For example if your input is 12 and 21 the output should be 22.
I like oRole's answer, but I think they're missing a couple things with the example input that you provided in your comment. I'll also point out some of the errors in the code that you have.
First off, if you're only given the input 12,23,34,45, then you don't need to call Console.ReadLine within your for loop. You've already gotten the input, you don't need to get any more (from what you've described).
Secondly, unless you're doing mathematical operations, there is no need to store numerical data as ints, keep it as a string, especially in this case. (What I mean is that you don't store Zip Codes in a database as a number, you store it as a string.)
Now, onto the code. You had the right way to get your data:
var listOfNumbers = Console.ReadLine();
At that point, listOfNumbers is equal to "12,23,34,45". If you iterate on that variable as a string, you'll be taking each individual character, including the commas. To get each of the numbers to operate on, you'll need to use string.Split.
var numbers = listOfNumbers.Split(',');
This turns that list into four different two character numbers (in string form). Now, you can iterate over them, but you don't need to worry about converting them to numbers as you're operating on the characters in each string. Also, you'll need a results collection to put everything into.
var results = new List<string>();
// Instead of the regular "i < numbers.Length", we want to skip the last.
for (var i = 0; i < numbers.Length - 1; i++)
{
var first = numbers[i];
var second = numbers[i + 1]; // This is why we skip the last.
results.Add(first[1] + second[0]);
}
Now your results is a collection of the numbers "22", "33", and "44". To get those back into a single string, you can use the helper method string.Join.
Console.WriteLine(string.Join(",", results));
You could use the string-method .Substring(..) to achieve what you want.
If you want to keep int-conversion in combination with user input, you could do:
int numA = 23;
int numB = 34;
int resultAB = Convert.ToInt16(numA.ToString().Substring(1, 1) + numB.ToString().Substring(0, 1));
Another option would be to take the users input as string values and to convert them afterwards like that:
string numC = "12";
string numD = "21";
int resultCD = Convert.ToInt16(numC.Substring(1, 1) + numD.Substring(0, 1));
I hope this code snippet will help you combining your numbers. The modulo operator (%) means: 53 / 10 = 5 Rest 3
This example shows the computation of the numbers 34 and 12
int firstNumber = 34 - (34 % 10) // firstNumber = 30
int secondNumber = 12 % 10; // secondNumber = 2
int combined = firstNumber + secondNumber; // combined = 32
EDIT (added reading and ouput code):
boolean reading = true;
List<int> numbers = new ArrayList();
while(reading)
{
try
{
int number = Convert.ToInt32(Console.ReadLine());
if (number > 9 && number < 100) numbers.Add(number);
else reading = false; // leave reading process if no 2-digit-number
}
catch (Exception ex)
{
// leave reading process by typing a character instead of a number;
reading = false;
}
}
if (numbers.Count() > 1)
{
List<int> combined = new ArrayList();
for (int i = 1; i <= numbers.Count(); i++)
{
combined.Add((numbers[i-1] % 10) + (numbers[i] - (numbers[i] % 10)));
}
//Logging output:
foreach (int combination in combined) Console.WriteLine(combination);
}
As you mention, if you already have both numbers, and they are always valid two digit integers, following code should work for you.
var num1 = 12;
var num2 = 22;
var result = (num2 / 10)*10 + (num1 % 10);
num2/10 returns the first digit of second number, and num1 % 10 returns the second digit of the first number.
The % and / signs are your savior.
If you want the 'ones' digit of a number (lets call it X), simply do X%10 - the remainder will be whatever number is in the 'ones' digit. (23%10=3)
If, instead, the number is two digits and you want the 'tens' digit, divide it by ten. (19/10=1).
To merge them, multiply the number you want to be in the 'tens' digit by ten, and add the other number to it (2*10+2=22)
There are other solutions like substring, etc and many one have already given it above. I am giving the solution VIA LINQ, note that this isn't efficient and it's recommended only for learning purpose here
int numA = 12;
int numB = 21 ;
string secondPartofNumA = numA.ToString().Select(q => new string(q,1)).ToArray()[1]; // first digit
string firstPartofNumB = numB.ToString().Select(q => new string(q,1)).ToArray()[0]; // second digit
string resultAsString = secondPartofNumA + firstPartofNumB;
int resultAsInt = Convert.ToInt32(resultAsString);
Console.WriteLine(resultAsString);
Console.WriteLine(resultAsInt);

How to get count of numbers in int and how to split a number without making a string

I have a number like 601511616
If all number's length is multiple of 3, how can a split the number into an array without making a string
Also, how can I count numbers in the int without making a string?
Edit: Is there a way to simply split the number, knowing it's always in a multiple of 3... good output should look like this: {616,511,601}
You can use i % 10 in order to get the last digit of integer.
Then, you can use division by 10 for removing the last digit.
1234567 % 10 = 7
1234567 / 10 = 123456
Here is the code sample:
int value = 601511616;
List<int> digits = new List<int>();
while (value > 0)
{
digits.Add(value % 10);
value /= 10;
}
// digits is [6,1,6,1,1,5,1,0,6] now
digits.Reverse(); // Values has been inserted from least significant to the most
// digits is [6,0,1,5,1,1,6,1,6] now
Console.WriteLine("Count of digits: {0}", digits.Count); // Outputs "9"
for (int i = 0; i < digits.Count; i++) // Outputs "601,511,616"
{
Console.Write("{0}", digits[i]);
if (i > 0 && i % 3 == 0) Console.Write(","); // Insert comma after every 3 digits
}
IDEOne working demonstration of List and division approach.
Actually, if you don't need to split it up but only need to output in 3-digit groups, then there is a very convenient and proper way to do this with formatting.
It will work as well :)
int value = 601511616;
Console.WriteLine("{0:N0}", value); // 601,511,616
Console.WriteLine("{0:N2}", value); // 601,511,616.00
IDEOne working demonstration of formatting approach.
I can't understand your question regarding how to split a number into an array without making a string - sorry. But I can understand the question about getting the count of numbers in an int.
Here's your answer to that question.
Math.Floor(Math.Log10(601511616) + 1) = 9
Edit:
Here's the answer to your first question..
var n = 601511616;
var nArray = new int[3];
for (int i = 0, numMod = n; i < 3; numMod /= 1000, i++)
nArray[i] = numMod%1000;
Please keep in mind there's no safety in this operation.
Edit#3
Still not perfect, but a better example.
var n = 601511616;
var nLength = (int)Math.Floor(Math.Log10(n) + 1)/ 3;
var nArray = new int[nLength];
for (int i = 0, numMod = n; i < nLength; numMod /= 1000, i++)
nArray[i] = numMod%1000;
Edit#3:
IDEOne example http://ideone.com/SSz3Ni
the output is exactly as the edit approved by the poster suggested.
{ 616, 511, 601 }
Using Log10 to calculate the number of digits is easy, but it involves floating-point operations which is very slow and sometimes incorrect due to rounding errors. You can use this way without calculating the value size first. It doesn't care if the number of digits is a multiple of 3 or not.
int value = 601511616;
List<int> list = new List<int>();
while (value > 0) // main part to split the number
{
int t = value % 1000;
value /= 1000;
list.Add(t);
}
// Convert back to an array only if it's necessary, otherwise use List<T> directly
int[] splitted = list.ToArray();
This will store the splitted numbers in reverse order, i.e. 601511616 will become {616, 511, 601}. If you want the numbers in original order, simply iterate the array backwards. Alternatively use Array.Reverse or a Stack
Since you already know they are in multiples of 3, you can just use the extracting each digit method but use 1000 instead of 10. Here is the example
a = 601511616
b = []
while(a):
b.append(a%1000)
a = a//1000
print(b)
#[616, 511, 601]

c# optimizing cycle working with big numbers

I have this code that finds numbers in a given range that contain only 3 and 5 and are polynoms(symetrical, 3553 for example). The problem is that the numbers are between 1 and 10^18, so there are cases in which I have to work with big numbers, and using BigInteger makes the program way too slow, so is there a way to fix this ? Here's my code:
namespace Lucky_numbers
{
class Program
{
static void Main(string[] args)
{
string startString = Console.ReadLine();
string finishString = Console.ReadLine();
BigInteger start = BigInteger.Parse(startString);
BigInteger finish = BigInteger.Parse(finishString);
int numbersFound = 0;
for (BigInteger i = start; i <= finish; i++)
{
if (Lucky(i.ToString()))
{
if (Polyndrome(i.ToString()))
{
numbersFound++;
}
}
}
}
static bool Lucky(string number)
{
if (number.Contains("1") || number.Contains("2") || number.Contains("4") || number.Contains("6") || number.Contains("7") || number.Contains("8") || number.Contains("9") || number.Contains("0"))
{
return false;
}
else
{
return true;
}
}
static bool Polyndrome(string number)
{
bool symetrical = true;
int middle = number.Length / 2;
int rightIndex = number.Length - 1;
for (int leftIndex = 0; leftIndex <= middle; leftIndex++)
{
if (number[leftIndex] != number[rightIndex])
{
symetrical = false;
break;
}
rightIndex--;
}
return symetrical;
}
}
}
Edit: Turns out it's not BigInteger, it's my shitty implementation.
You could use ulong:
Size: Unsigned 64-bit integer
Range: 0 to 18,446,744,073,709,551,615
But I would guess that BigInteger is not a problem here. I think you should create algorithm for palindrome creation instead of brute-force increment+check solution.
Bonus
Here is a palyndrome generator I wrote in 5 minutes. I think it will be much faster than your approach. Could you test it and tell how much faster it is? I'm curious about that.
public class PalyndromeGenerator
{
private List<string> _results;
private bool _isGenerated;
private int _length;
private char[] _characters;
private int _middle;
private char[] _currentItem;
public PalyndromeGenerator(int length, params char[] characters)
{
if (length <= 0)
throw new ArgumentException("length");
if (characters == null)
throw new ArgumentNullException("characters");
if (characters.Length == 0)
throw new ArgumentException("characters");
_length = length;
_characters = characters;
}
public List<string> Results
{
get
{
if (!_isGenerated)
throw new InvalidOperationException();
return _results.ToList();
}
}
public void Generate()
{
_middle = (int)Math.Ceiling(_length / 2.0) - 1;
_results = new List<string>((int)Math.Pow(_characters.Length, _middle + 1));
_currentItem = new char[_length];
GeneratePosition(0);
_isGenerated = true;
}
private void GeneratePosition(int position)
{
if(position == _middle)
{
for (int i = 0; i < _characters.Length; i++)
{
_currentItem[position] = _characters[i];
_currentItem[_length - position - 1] = _characters[i];
_results.Add(new string(_currentItem));
}
}
else
{
for(int i = 0; i < _characters.Length; i++)
{
_currentItem[position] = _characters[i];
_currentItem[_length - position - 1] = _characters[i];
GeneratePosition(position + 1);
}
}
}
}
Usage:
var generator = new PalyndromeGenerator(6, '3', '5');
generator.Generate();
var items = generator.Results.Select(x => ulong.Parse(x)).ToList();
Strange riddle, but can be simplified if I understand the requirement.
I would first map these numbers to binary as there is only two possible
"lucky" digits, then generate the numbers by counting in binary until
I have completed nine bits. Reflect it for the full number, then
convert 0 to 3 and 1 to 5.
Example 1101
Reflect it = 10111101 --> 53555535
Do this from 0 all the way to 111111111
Declare start and finish to be static inside the class.
Change the method Lucky to:
static bool Lucky(string number)
{
return !(number.Contains("1") || number.Contains("2") || number.Contains("4") || number.Contains("6") || number.Contains("7") || number.Contains("8") || number.Contains("9") || number.Contains("0"));
}
Also, you can use Parallel library to parallelize the computation.
Instead of using a regular for loop, you could use a Parallel.For.
Look at the problem a different way - how many strings of up to 9 characters (using only '3' and '5') can you make? for each string you have 2 palindromes (one repeating the last character, one not) that you can make.
e.g.
3 -> 33
5 ->, 55
33 -> 333, 3333
35 -> 353, 3553
53 -> 535, 5335
...
The only suggestion I have is to use a 3rd party library like intx, or some unmanaged code. The intx author reports that it can work faster than BigInteger in some situations: "System.Numerics.BigInteger class was introduced in .NET 4.0 so I was interested in performance of this solution. I did some tests (grab test code from GitHub) and it appears that BigInteger has performance in general comparable with IntX on standard operations but starts losing when FHT comes into play (when multiplying really big integers, for example)."
Since the number has to be symmetrical, you only need to check the first half of the number. You don't need to check 18 digits, you only have to check to 9 digits and then swap the order of the characters and add them to the back as a string.
One thing I can think of is if you are only going to count integers that are containing 3 or 5 you don't need to traverse the entire list of numbers between your beginning & ending range.
Instead, look at your character set as either '3' or '5'. Then you can simply go through the allowed permutations of half of the number itself, leaving the other half to be completed to successfully create a polyndrome.
There are some rules to this method which would help, such as :
if the starting number's left-most digit was greater than 5 there is no need to attempt for that specific number of digits.
if both numbers fall on the same amount of digits but left-most digits do not traverse / include 5 or 3, no need to process.
Developing some set of rules such as this may help other than attempting to check every possible permutation.
So, for example, your Lucky function would become something more along the lines of :
static bool Lucky(string number)
{
if((number[0] != '3') && (number[0] != '5'))
{
return false;
} //and you could continue this for the entire string
...
}

C# char calculation problem

Im trying to do a permutation. of five in this case, so 5,4,3,2,1 . Eventually I want it to permute up to 100 which can be stored in my intX class. the calculation is fine, but I want to add up all individual numbers of the output, using the script below.
so 5! = 5x4x3x2x1 = 120 ----> 1+2+0 = 3. BUT My script below gives the output 147:
120
1
2
0
147
What am I doing wrong? I allready tried all converts, I started with just using the string[pointer] thingy, I tried different arrays etc.. but it all keeps coming up with 147. Is it some kind of representation thing?
static void Main(string[] args)
{
IntX total=1;
IntX totalsum = 0;
int perm = 5;
for (int i = perm; i > 0; i--)
{
total = total * i;
}
Console.WriteLine(total);
string answerstring = Convert.ToString(total);
char[] answerArray = answerstring.ToArray();
for (int x = 0; x < answerArray.Length; x++)
{
totalsum += Convert.ToInt32(answerArray[x]);
Console.WriteLine(answerArray[x]);
}
Console.WriteLine(totalsum);
}
The problem is the way you are converting your answerArray elements back to numbers
Convert.ToInt32(answerArray[x])
The above line takes the char 1 and converts it to an int. This is not the same as parsing it as an int. 1 is ascii character 49 so internally the char has an int representation of 49 and so that is what it is converted to (since this is just trying to do a type conversion rather than any kind of processing)
Similarly 2 = 50 and 0 = 48 so you get the total of 147.
What you want to do is use Integer.Parse to parse strings as numbers. I believe it should implicitly convert the char to a string before parsing it.
So your loop would be:
for (int x = 0; x < answerArray.Length; x++)
{
totalsum += int.Parse(answerArray[x].ToString());
Console.WriteLine(answerArray[x]);
}
You can also do it the way others suggested with subtracting chars. This works because the ascii value of 1 is 1 higher than the ascii value for 0. 2 is 2 higher, etc.
Of course this only works with single digit chars. If you ever want to convert more than two digit numbers into int from a string you'll need int.parse.
For what its worth I suspect that the character subtraction method is the most efficient since it is effectively just doing some very simple type conversion and subtraction. The parse method is likely to do a lot more stuff and so be a bit more heavyweight. I dont' you will notice a performance difference though.
The problem lies in here:
for (int x = 0; x < answerArray.Length; x++)
{
//Casting char to int, not what you want!
//totalsum += Convert.ToInt32(answerArray[x]);
//Parsing char to int, what you do want!
totalsum += int.Parse(answerArray[x]);
Console.WriteLine(answerArray[x]);
}
Instead of converting to an integer (which will take the ASCII character value), try using answerArray[x] - '0'.
(int)'0' is not equal to 0. You should use ((int)answerArray[x] - (int)'0')
Why bother changing it to a char array? You already have the information that you need.
while (total > 0)
{
ones_digit = total % 10;
totalsum += ones_digit;
total -= ones_digit;
total /= 10;
}
Convert.ToInt32 returns the Unicode values of characters 1, 2 and 0 which are 49, 50 and 48. That's why the sum comes out as 147.

Categories