How to get the maximum number of a particular length - c#

I have a number, for example 1234567897865; how do I max it out and create 99999999999999 ?
I did this this way:
int len = ItemNo.ToString().Length;
String maxNumString = "";
for (int i = 0; i < len; i++)
{
maxNumString += "9";
}
long maxNumber = long.Parse(maxNumString);
what would be the better, proper and shorter way to approach this task?

var x = 1234567897865;
return Math.Pow(10, Math.Ceiling(Math.Log10(x+1e-6))) - 1;
To expand on comments below, if this problem was expressed in hex or binary, it could be done very simply using shift operators
i.e., "I have a number, in hex,, for example 3A67FD5C; how do I max it out and create FFFFFFFF?"
I'd have to play with this to make sure it works exactly, but it would be something like this:
var x = 0x3A67FD5C;
var p = 0;
while((x=x>>1)>0) p++; // count how many binary values are in the number
return (1L << 4*(1+p/4)) - 1; // using left shift, generate 2 to
// that power and subtract one

long maxNumber = long.Parse(new String('9', ItemNo.ToString().Length));

Try this:
int v = 1;
do {
v = v * 10;
} while (v <= number);
return v - 1;

int numDigits = (int)Math.Ceiling(Math.Log10(number));
int result = (int)(Math.Pow(10, numDigits) - 1)
I don't have a compiler available at the moment, so some additional string/double conversions may need to happen here.

Related

Get Binary Placement

I want to get the binary placement of a number.
int val = 1 << 9;
Console.WriteLine(val); //512
What I have now is the opposite. I have the value 512 and I want to get 9.
Thanks.
You want to find a binary logarithm, you can do either explictly:
int value = 512;
...
int result = (int) (Math.Log(value) / Math.Log(2));
or by a simple loop:
int value = 512;
...
int result = -1;
for (; value != 0; value /= 2, ++result);
Console.Write(result);
Convert.ToInt32(String, Int32) lets you specify the base:
int output = Convert.ToInt32(input, 2);

C# - Calculation in for loop not doing a correct calculation?

The program doesn't calculate/display the correct calculation/number correctly
I'm trying to learn some C# for Unity game development, and tried out some random math stuff, but something seems to not work and I can't figure out why.
Console.WriteLine("What is the total amount you'd like change for? For example: 41,15");
double change = Convert.ToDouble(Console.ReadLine());
// 500 200 100 50 20 10 5
// 2 1 0,50 0,20 0,10 0,05
int fivehundred = 0, twohundred = 0, onehundred = 0, fifty = 0, twenty = 0, ten = 0, five = 0;
int ctwo = 0, cone = 0, cfifty = 0, ctwenty = 0, cten = 0, cfive = 0;
for (int i = 0; change >= 500; i++)
{
change -= 500;
fivehundred++;
}
for (int i = 0; change >= 200; i++)
{
change -= 200;
twohundred++;
}
for (int i = 0; change >= 100; i++)
{
change -= 100;
onehundred++;
}
for (int i = 0; change >= 50; i++)
{
change -= 50;
fifty++;
}
for (int i = 0; change >= 20; i++)
{
change -= 20;
twenty++;
}
for (int i = 0; change >= 10; i++)
{
change -= 10;
ten++;
}
for (int i = 0; change >= 5; i++)
{
change -= 5;
five++;
}
for (int i = 0; change >= 2; i++)
{
change -= 2;
ctwo++;
}
for (int i = 0; change >= 1; i++)
{
change -= 1;
cone++;
}
for (int i = 0; change >= 0.50; i++)
{
change -= 0.50;
cfifty++;
}
for (int i = 0; change >= 0.20; i++)
{
change -= 0.20;
ctwenty++;
}
for (int i = 0; change >= 0.10; i++)
{
change -= 0.10;
cten++;
}
for (int i = 0; change >= 0.05; i++)
{
change -= 0.05;
cfive++;
}
Console.WriteLine("500x {0}, 200x {1}, 100x {2}, 50x {3}, 20x {4}, 10x {5}, 5x {6}, 2x {7}, 1x {8}, 0,50x {9}, 0,20x {10}, 0,10x {11}, 0,05x {12}", fivehundred, twohundred, onehundred, fifty, twenty, ten, five, ctwo, cone, cfifty, ctwenty, cten, cfive);
Even though there's still 5 cents left, the result gives me is this:
(this is when I entered 0,15 cents)
What is the total amount you'd like change for? For example: 41,15
0,15
500x 0, 200x 0, 100x 0, 50x 0, 20x 0, 10x 0, 5x 0, 2x 0, 1x 0, 0,50x 0, 0,20x 0, 0,10x 1, 0,05x 0
Press any key to continue . . .
If it's €0,09 or below, it does display that it needs 0,05 1x, but with anything above it with a remaining 5 cents, it doesn't. Everything else works as intended so far though.
(Also, any tips how I can make the code more efficient?)
I think this is what you are trying to do, but instead of using division, you are doing successive subtractions.
class Program
{
static void Main(string[] args)
{
int[] change = Currency.MakeChange(41.37m);
decimal sum = 0m;
for (int i = 0; i < change.Length; i++)
{
var amount = change[i]*Currency.Denominations[i];
sum += amount;
Debug.WriteLine($"{change[i]}×{Currency.Denominations[i]}");
}
Debug.WriteLine($"sum={sum}");
// output:
// 0×500
// 0×200
// 0×100
// 0×50
// 2×20
// 0×10
// 0×5
// 0×2
// 1×1
// 0×0.5
// 1×0.2
// 1×0.1
// 1×0.05
// 2×0.01
// sum=41.37
}
}
public class Currency
{
public static readonly decimal[] Denominations =
new decimal[] { 500m, 200m, 100m, 50m, 20m, 10m, 5m, 2m, 1m, 0.5m, 0.2m, 0.1m, 0.05m, 0.01m };
public static int[] MakeChange(decimal value)
{
int[] change = new int[Denominations.Length];
decimal remain = value;
for (int i = 0; i < Denominations.Length; i++)
{
// get the next note (amount in currency).
// must move from highest to smallest value.
decimal note = Denominations[i];
// can you divide the remainder with the note
int qty = (int)(decimal.Floor(remain/note));
change[i] = qty;
// calculate remaining amount
remain -= qty*note;
}
return change;
}
}
First of all, yes, you can simplify your code by A LOT just by replacing the for loops with while loops.
Second, to answear your actual question. The program does not enter the for loops because 0.05 it's not actually 0.05 because of how computers store floating point values in memory. EX.: 1/3 != 0.333333. To prevent this use the decimal data type.
Better explanation here and in the official C# Docs here under Precision in Comparisions.
Your code works as-is if you change from double to type decimal. There is a rounding error that occurs when using double precision, when I ran it 15-10 came out to 0.4999999999. Decimal has greater precision, so I would start there. You can figure this out either by setting breakpoints in your loops and stepping through them, or by adding Console.Writeline(change) in each loop so you can see what is happening. The debugger is your friend. That being said, lets clean up this code
Console.WriteLine("What is the total amount you'd like change for? For example: 41,15");
decimal change = Convert.ToDecimal(Console.ReadLine());
// 500 200 100 50 20 10 5
// 2 1 0,50 0,20 0,10 0,05
decimal[] currencyValues = {500m, 200m, 100m, 50m, 20m, 10m, 5m, 2m, 1m, .50m, .20m, .10m, 0.05m};
int[] returnChange = new int[13];
for(int i = 0; i < currencyValues.Length; i++)
{
if(change >= currencyValues[i])
{
returnChange[i] = (int)(change / currencyValues[i]);
change = change % currencyValues[i];
}
Console.Write($"{currencyValues[i]}x {returnChange[i]} ");
}
We can make use of arrays so we don't have to duplicate so much. So we have one array that holds the values of each denomination of currency, and then another array for the count of each denomination in the resulting change. Then we can go through each currency amount and do our calculations in one loop.
So first, we check to make sure we have at least as much change as the amount we are checking against. No need to calculate how many currency of value 5 we need to return if they only have 3, for example. Thats pretty intuitive so lets move on to the next part.
First, we divide the change left by each currency value. We only want whole numbers, we can't give someone half of a coin, after all. So we cast to integer to round the result and make it fit into our returnChange array. The next part is probably gonna look weird if you haven't seen the modulo operator % before. This basically says
Perform the division. But, rather than assigning the result of the division, assign the `remainder` instead
So if we have .70 currency, and we took out .50 for the change, the modulo % operator will say we have .20 currency remaining.
Hope this helped.
Refactor common code into reusable components. For example, your logic to calculate the count of a denomination is the same except for the denomination value and remaining balance, so create a function to abstract that logic:
// `ref` passes the decimal value in by reference, meaning any
// changes made to that parameter are also made to the variable
// passed into the method/function (by default a copy is made
// and changes here have no side effects
public int CashOut(decimal denomination, ref decimal balance)
{
var result = 0;
for (int i = 0; change >= denomination; i++)
{
balance -= denomination;
result++;
}
return result;
}
As a comment pointed out, a for loop isn't ideal here - you're not using
the variable i at all; a while loop is more appropriate:
public int CashOut( decimal denomination, ref decimal balance )
{
var result = 0;
while( balance >= denomination )
{
balance -= denomination;
++result; // preincrement operator has better performance
}
return result;
}
There are still better ways to perform your desired calculation; as another
answer pointed out, you can use division:
public int CashOut( decimal denomination, ref decimal balance )
{
var result = Convert.ToInt32( balance / denomination );
balance -= result * denomination;
return result;
}
If you didn't abstract the calculation changes, each change would require you to edit your N for loops; with this abstraction, you only have to edit it in a single place.
Replacing your for loops would look something like:
fivehundred = CashOut( 500.0M, ref change );
twohundred = CashOut( 200.0M, ref change );
// etc.
But that's still highly repetitive. As another answer and comment pointed out, you can configure an array of denominations (and results) to process sequentially:
var denominations = new[]{ 500.0M, 200.0M, 100.0M }
var results = new int[denominations.Length];
for( var i = 0; i < denominations.Length; ++i )
{
results[i] = CashOut( denominations[i], ref change );
}
But you don't need that for loop if you use LINQ!
var denominations = new[]{ 500.0M, 200.0M, 100.0M };
var results = denominations.Select( d => CashOut( d, change ) )
.ToArray();
Your output could then be written as:
for( var i = 0; i < denominations; ++i )
{
Console.Write( $"{denominations[0]}x {results[i]} " )
}
Console.WriteLine();
How about projecting an anonymous type to keep the denomination paired with its result?
var denominations = new[]{ 500.0M, 200.0M, 100.0M };
var results = denominations.Select( d =>
new
{
Denomination = d,
Count = CashOut( d, change ),
} );
Then your output could look like:
foreach(var result in results)
{
Console.Write( $"{result.Denomination}x {result.Count} " );
}
Console.WriteLine();
If you wanted to find out how many 200's were in the results, you can find it easily:
var twoHundreds = results.FirstOrDefault(r => r.Denomination == 200.0M)
?.Count // ?. means execute the following statement(s) if the value is not null
?? 0M; // ?? is the null coalescing operator meaning return this value if the precedeing is null

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 number inside of a string and do a loop

I want to get a number of a string, and separate the string and the number, and then, do a loop and call a method the number of times the string says.
The string has to have this structure: "ABJ3" (Only one number accepted and 3 characters before it)
This is my code, but it repeat hundred of times, I don't know why
int veces = 0;
for (int i = 0; i < m.Length; i++)
{
if (Char.IsDigit(m[i]))
veces = Convert.ToInt32(m[i]);
}
if (m.Length == 4)
{
for (int i = 0; i <= veces; i++)
{
m = m.Substring(0, 3);
operaciones(m, u, t);
Thread.Sleep(100);
}
}
operaciones(m,u,t);
if (u.Length >= 14)
{
u = u.Substring(0, 15);
}
Some help please?
You have to convert your m[i] ToString() right now you are sending the char value to Convert.ToInt32 and that is a much higher value (9 = 57 for example)
char t = '9';
int te = Convert.ToInt32(t.ToString());
Console.WriteLine(te);
This gives us a result of 9 but
char t = '9';
int te = Convert.ToInt32(t);
Console.WriteLine(te);
Gives us a result of 57
So you need to change
veces = Convert.ToInt32(m[i]);
to
veces = Convert.ToInt32(m[i].ToString());
Hope it helped.
Best regards //KH.
You cannot convert the digits like this. You're overwriting them and taking only the last one. Moreover, you're taking its ASCII code, not digit value. You have to extract all digits first then convert them:
int position = 0;
int veces = 0;
string temp = ""
for (int i = 0; i < m.Length; i++) {
if (Char.IsDigit(m[i]))
position = i;
else
break;
}
veces = Convert.ToInt32(m.SubString(0, i + 1));
Alternatively, you can use regex instead.

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