I need to divide a variable distance in a very specific way. The spacing for the divisions must be 40 units minimum, and 80 units maximum.
I've tried several different various of this code but I am struggling to wrap my head around how to include the min/max variable in my division.
double totaldist = X;
double division = totaldist / 80;
double roundup = Math.Ceiling(division);
double space = totaldist / roundup;
double increment = 0;
while (increment < totaldist)
{
increment = increment + space;
}
The attached code is obviously short of what I want to accomplish, I'm not sure how to bridge the gap. Thank you
So all you have to do is loop over all the possible divisors and pick the best one. The simplest way to accomplish this is as follows:
public static int remainder(int totalDist)
{
double minRemainder = (totalDist % 40) / 40;
int bestDivision = 40;
for (var i = 40; i <= 80; i++)
{
double cRemainder = (totalDist % i) / i;
if (totalDist % i == 0) return i;
else if (cRemainder < minRemainder) { minRemainder = cRemainder; bestDivision = i; }
}
return bestDivision;
}
This will always return the closest result. Even if there is no real solution, it will still provide an approximate answer as a fallback.
I'd test every divisor for mod 0 (no remainder)
int d = 420;
int s = 40;
for(; s <= 80; s++){
if(d%s==0)
break;
}
if(s==81)
Console.Write("There is no suitable divisor");
else
Console.Write($"{d} divides into {s} segments of {d/s} with no remainder");
If you want to minimise the segment length (greater number of segments) start at 80 and work towards 40 in the loop instead - set your d to 480, start at 80 and you should get "80 segments of length 6" rather than "40 segments of length 12"
You can even get cute with your loop and have no body:
for(; s <= 80 && d%s > 0; s++){ }
But it's not quite so readable/self explanatory
Related
Reversing a while loop, I don't know if it's the correct way to ask the question, but come on. I have a code that converts any whole number to a two or three digit decimal. How?
dividing the integer value by two until it is less than 10, counting in turn the times it divided it in the redo variable, thus we obtain the tenth: decimal = (integer, redo):
int InitialInteger = 190;
int Integer = InitialInteger;
int redo = 0;
while (Integer > 10)
{
Integer = Integer / 2;
redo++;
}
//Salida: 5,5
Now I want to get back the initial integer value ("reverse the loop") that is, multiply the integer part by 2 as many times as the decimal part indicates: Integer = (decimal1 * 2)^decimal2
int decimal1 = Int16.Parse(Decimal.Split(',')[0]);
int decimal2 = Int16.Parse(Decimal.Split(',')[1]);
while (decimal2 > 0)
{
redo -= 1;
InitialInteger += decimal2 * 2;
}
//Salida: 60
but it doesn't work, it never returns the initial value!
Any idea?
Note that you have to set Integer as a float instead of as int for it to work.
Use this instead
int InitialInteger = 190;
float temp = InitialInteger;
int redo = 0;
while (temp > 10)
{
temp= temp / 2;
redo++;
}
and then to reverse
while (redo > 0)
{
temp = temp * 2;
redo--;
}
At the end temp (or Integer as you called it!) is again 190
Update 01
Thanks to Caius, found the main problem, the logic on the "if" was wrong, now fixed and giving the correct results. The loop still create more positions than needed on the secondary List, an extra position for each number on the main List.
I've updated the code bellow for refence for the following question:
-001 I can figure out why it create positions that needed, the for loop should run only after the foreach finishes its loops correct?
-002 To kind of solving this issue, I've used a List.Remove() to remove all the 0's, so far no crashes, but, the fact that I'm creating the extra indexes, and than removing them, does means a big performance down if I have large list of numbers? Or is an acceptable solution?
Description
It supposed to read all numbers in a central List1 (numberList), and count how many numbers are inside a certain (0|-15 / 15|-20) range, for that I use another List, that each range is a position on the List2 (numberSubList), where each number on List2, tells how many numbers exists inside that range.
-The range changes as the numbers grows or decrease
Code:
void Frequency()
{
int minNumb = numberList.Min();
int maxNumb = numberList.Max();
int size = numberList.Count();
numberSubList.Clear();
dGrdVFrequency.Rows.Clear();
dGrdVFrequency.Refresh();
double k = (1 + 3.3 * Math.Log10(size));
double h = (maxNumb - minNumb) / k;
lblH.Text = $"H: {Math.Round(h, 2)} / Rounded = {Math.Round(h / 5) * 5}";
lblK.Text = $"K: {Math.Round(k, 4)}";
if (h <= 5) { h = 5; }
else { h = Math.Round(h / 5) * 5; }
int counter = 1;
for (int i = 0; i < size; i++)
{
numberSubList.Add(0); // 001 HERE, creating more positions than needed, each per number.
foreach (int number in numberList)
{
if (number >= (h * i) + minNumb && number < (h * (i + 1)) + minNumb)
{
numberSubList[i] = counter++;
}
}
numberSubList.Remove(0); // 002-This to remove all the extra 0's that are created.
counter = 1;
}
txtBoxSubNum.Clear();
foreach (int number in numberSubList)
{
txtBoxSubNum.AppendText($"{number.ToString()} , ");
}
lblSubTotalIndex.Text = $"Total in List: {numberSubList.Count()}";
lblSubSumIndex.Text = $"Sum of List: {numberSubList.Sum()}";
int inc = 0;
int sum = 0;
foreach (int number in numberSubList)
{
sum = sum + number;
int n = dGrdVFrequency.Rows.Add();
dGrdVFrequency.Rows[n].Cells[0].Value = $"{(h * inc) + minNumb} |- {(h * (1 + inc)) + minNumb}";
dGrdVFrequency.Rows[n].Cells[1].Value = $"{number}";
dGrdVFrequency.Rows[n].Cells[2].Value = $"{sum}";
dGrdVFrequency.Rows[n].Cells[3].Value = $"{(number * 100) / size} %";
dGrdVFrequency.Rows[n].Cells[4].Value = $"{(sum * 100) / size} %";
inc++;
}
}
Screen shot showing the updated version.
I think, if your aim is to only store eg 17 in the "15 to 25" slot, this is wonky:
if (number <= (h * i) + minNumb) // Check if number is smaller than the range limit
Because it's found inside a loop that will move on to the next range, "25 to 35" and it only asks if the number 17 is less than the upper limit (and 17 is less than 35) so 17 is accorded to the 25-35 range too
FWIW the range a number should be in can be derived from the number, with (number - min) / number_of_ranges - at the moment you create your eg 10 ranges and then you visit each number 10 times looking to put it in a range, so you do 9 times more operations than you really need to
I am trying to create some kind of heatmap to visualize data I get from a sensor. So far this works but it looked odd. So I figured out that my code which normalizes the values (ranging from at least -100 to 100) must be invalid.
I often got exceptions because the factor (the normalized value) I use to calculate the color (byte) was negative or greater than 1.
So I modified my code and basically shifted min, max and the value by Math.Abs(min) to ensure that my values are positive. The negative issue is fixed but I sometimes end up with values like 1.02xxxx which must not happen. EDIT: Still getting negative values in some cases...
This is my code so far:
double min = data.Min();
double max = data.Max();
double avg = data.Average();
double v = max - min;
byte a, b, g, r;
// Set minimum and maximum
Dispatcher.InvokeAsync(() =>
{
Minimum = min;
Maximum = max;
Average = avg;
});
double shift = 0;
if (min < 0) // If minimum is negative, shift it to 0 and everything else positively by Abs(min)
{
max += shift = Math.Abs(min);
min += shift;
}
int skipFactor = (int)(1 / _pointResolution);
for (int i = 0; i < data.Length; i += skipFactor)
{
// If min == 0 then shift data
double value = Math.Abs(min) < 0.0001d ? (data[i] + shift) / max : (data[i] - min) / v;
...
}
How can I fix this without adding rounding or "edge-cases"? I assume the Math.Abs() combined with adding operations results in slightly off values... But there must be a solution to that, right?
Ok so this is kind of weird. I have an algorithm to find the highest possible numerical palindrome that is a multiple of two factors who each have K digits.
The method I'm using to find the highest valid palindrome is to look at the highest possible palindrome for the number set (i.e. if k=3, the highest possible is 999999, then 998899, etc). Then I check if that palindrome has two factors with K digits.
For debugging, I thought it would be a good idea to print to the console each of the palindromes I was checking (to make sure I was getting them all. To my surprise, adding
Console.WriteLine(palindrome.ToString());
to each iteration of finding a palindrome dropped my runtime a whopping 10 seconds from ~24 to ~14.
To verify, I ran the program several times, then commented out the Console command and ran that several times, and every time it was shorter with the Console command.
This just seems weird, any ideas?
Here's the source if anyone wants to take a whack at it:
static double GetHighestPalindromeBench(int k)
{
//Because the result of k == 1 is a known quantity, and results in aberrant behavior in the algorithm, handle as separate case
if (k == 1)
{
return 9;
}
/////////////////////////////////////
//These variables will be used in HasKDigitFactors(), no need to reprocess them each time the function is called
double kTotalSpace = 10;
for (int i = 1; i < k; i++)
{
kTotalSpace *= 10;
}
double digitConstant = kTotalSpace; //digitConstant is used in HasKDigits() to determine if a factor has the right number of digits
double kFloor = kTotalSpace / 10; //kFloor is the lowest number that has k digits (e.g. k = 5, kFloor = 10000)
double digitConstantFloor = kFloor - digitConstant; //also used in HasKDigits()
kTotalSpace--; //kTotalSpace is the highest number that has k digits (e.g. k = 5, kTotalSpace = 99999)
/////////////////////////////////////////
double totalSpace = 10;
double halfSpace = 10;
int reversionConstant = k;
for (int i = 1; i < k * 2; i++)
{
totalSpace *= 10;
}
double floor = totalSpace / 100;
totalSpace--;
for (int i = 1; i < k; i++)
{
halfSpace *= 10;
}
double halfSpaceFloor = halfSpace / 10; //10000
double halfSpaceStart = halfSpace - 1; //99999
for (double i = halfSpaceStart; i > halfSpaceFloor; i--)
{
double value = i;
double palindrome = i;
//First generate the full palindrome
for (int j = 0; j < reversionConstant; j++)
{
int digit = (int)value % 10;
palindrome = palindrome * 10 + digit;
value = value / 10;
}
Console.WriteLine(palindrome.ToString());
//palindrome should be ready
//Now we check the factors of the palindrome to see if they match k
//We only need to check possible factors between our k floor and ceiling, other factors do not solve
if (HasKDigitFactors(palindrome, kTotalSpace, digitConstant, kFloor, digitConstantFloor))
{
return palindrome;
}
}
return 0;
}
static bool HasKDigitFactors(double palindrome, double totalSpace, double digitConstant, double floor, double digitConstantFloor)
{
for (double i = floor; i <= totalSpace; i++)
{
if (palindrome % i == 0)
{
double factor = palindrome / i;
if (HasKDigits(factor, digitConstant, digitConstantFloor))
{
return true;
}
}
}
return false;
}
static bool HasKDigits(double value, double digitConstant, double digitConstantFloor)
{
//if (Math.Floor(Math.Log10(value) + 1) == k)
//{
// return true;
//}
if (value - digitConstant > digitConstantFloor && value - digitConstant < 0)
{
return true;
}
return false;
}
Note that I have the Math.Floor operation in HasKDigits commented out. This all started when I was trying to determine if my digit check operation was faster than the Math.Floor operation. Thanks!
EDIT: Function call
I'm using StopWatch to measure processing time. I also used a physical stopwatch to verify the results of StopWatch.
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
double palindrome = GetHighestPalindromeBench(6);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}:{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10);
Console.WriteLine();
Console.WriteLine(palindrome.ToString());
Console.WriteLine();
Console.WriteLine(elapsedTime);
I have tested your code. My system is an i7-3770 3.40 GHz, quad-core with hyperthreading, so 8 cores available.
Debug build, with and without the console Writeline statement (commented out or not), in debug mode or not, the times vary from about 8.7 to 9.8 sec. As a Release build it comes down to about 6.8-7.0 sec either way. Th figures were the same inside VS and from the command line. So your observation is not reproduced.
On performance monitor with no console output I see one core at 100%, but it switches between cores 1,4,5 and 8. Without console output there is activity on other cores. Max CPU usage never exceeds 18%.
In my judgment your figure with console output is probably consistent with mine, and represents the true value. So your question should read: why is your system so slow when it's not doing console output?
The answer is: because there is something different about your computer or your project which we don't know about. I've never seen this before, but something is soaking up cycles and you should be able to find out what it is.
I've written this as an answer although it isn't really an answer. If you get more facts and update your question, hopefully I can provide a better answer.
I am trying to place currency trades that match an exact rate on a market that only accepts integral bid/offer amounts. I want to make the largest trade possible at a specific rate. This is a toy program, not a real trading bot, so I am using C#.
I need an algorithm that returns an answer in a reasonable amount of time even when the numerator and denominator can be large (100000+).
static bool CalcBiggestRationalFraction(float target_real, float epsilon, int numerator_max, int denominator_max, out int numerator, out int denominator)
{
// target_real is the ratio we are tryig to achieve in our output fraction (numerator / denominator)
// epsilon is the largest difference abs(target_real - (numerator / denominator)) we are willing to tolerate in the answer
// numerator_max, denominator_max are the upper bounds on the numerator and the denominator in the answer
//
// in the case where there are multiple answers, we want to return the largest one
//
// in the case where an answer is found that is within epsilon, we return true and the answer.
// in the case where an answer is not found that is within epsilon, we return false and the closest answer that we have found.
//
// ex: CalcBiggestRationalFraction(.5, .001, 4, 4, num, denom) returns (2/4) instead of (1/2).
}
I asked a previous question that is similar (http://stackoverflow.com/questions/4385580/finding-the-closest-integer-fraction-to-a-given-random-real) before I thought about what I was actually trying to accomplish and it turns out that I am trying to solve a different, but related problem.
The canonical way to solve your problem is with continued fraction expansion. In particular, see this section.
If you want the unreduced fraction, then here's one optimization you can do: Since you'll never be interested in n/2, because you want 2n/4, 4n/8, or 1024n/2048, we only need to check some of the numbers. As soon as we check any multiple of 2, we never need to check 2. Therefore, I believe you can try denominators denominator_max through denominator_max/2, and you'll have implicitly checked all of the factors of those numbers, which would be everything 2 through denominator_max/2.
I'm not at a compiler at the moment, so I haven't checked this code for correctness, or even that it compiles, but it should be close.
static bool CalcBiggestRationalFraction(float target_real, float epsilon,
int numerator_max, int denominator_max,
out int numerator, out int denominator)
{
if((int)Math.Round(target_real * denominator_max) > numerator_max)
{
// We were given values that don't match up.
// For example, target real = 0.5, but max_num / max_den = 0.3
denominator_max = (int)(numerator_max / target_real);
}
float bestEpsilon = float.MAX_VALUE;
for(int den = denominator_max; den >= denominator_max/2, den--)
{
int num = (int)Math.Round(target_real * den);
float thisEpsilon = Math.abs(((float)num / den) - target_real);
if(thisEpsilon < bestEpsilon)
{
numerator = num;
denominator = den;
bestEpsilon = thisEpsilon;
}
}
return bestEpsilon < epsilon;
}
Let's try this:
First, we need to turn the float into a fraction. Easiest way I can think to do this is to find the order of magnitude of the epsilon, multiply the float by that order, and truncate to get the numerator.
long orderOfMagnitude = 1
while(epsilon * orderOfMagnitude <1)
orderOfMagnitude *= 10;
numerator = (int)(target_real*orderOfMagnitude);
denominator = orderOfMagnitude;
//sanity check; if the initial fraction isn't within the epsilon, then add sig figs until it is
while(target_real - (float)numerator / denominator > epsilon)
{
orderOfMagnitude *= 10;
numerator = (int)(target_real*orderOfMagnitude);
denominator = orderOfMagnitude;
}
Now, we can break the fraction down into least terms. The most efficient way I know of is to attempt to divide by all prime numbers less than or equal to the square root of the smaller of the numerator and denominator.
var primes = new List<int>{2,3,5,7,11,13,17,19,23}; //to start us off
var i = 0;
while (true)
{
if(Math.Sqrt(numerator) < primes[i] || Math.Sqrt(denominator) < primes[i]) break;
if(numerator % primes[i] == 0 && denominator % primes[i] == 0)
{
numerator /= primes[i];
denominator /= primes[i];
i=0;
}
else
{
i++;
if(i > primes.Count)
{
//Find the next prime number by looking for the first number not divisible
//by any prime < sqrt(number).
//We are actually unlikely to have to use this, because the denominator
//is a power of 10, so its prime factorization will be 2^x*5^x
var next = primes.Last() + 2;
bool add;
do
{
add = true;
for(var x=0; primes[x] <= Math.Sqrt(next); x++)
if(next % primes[x] == 0)
{
add = false;
break;
}
if(add)
primes.Add(next);
else
next+=2;
} while(!add);
}
}
}