I start with figures in line 1 for columns A nd B, (see below) 890 and 450 and both are divided by 1.2 to get a net figure (line 2), the results of which are then split over two types (say salesA and salesB)
How can I ensure that the sum of salesA + salesB will always be equal to the values shown on line 2 which in turn will be equal to values on line 1 when multiplied by 20%.
As you can see, column B is out by 0.02
Example
column A column B
890.00 /1.2 450.00 /1.2
741.67 375.00
333.33 salesA 208.35 salesA
408.34 salesB 166.67 salesB
741.67 375.02 sum of salesA + sales B
Values on line 2 multiplied by 20% should be equal to values on line 1
How can this be achieved ? I am aware of Math.Round.
Have tried inserting it everywhere but it doesn’t work
The division operator is inside a select statement
You are doing something like this when splitting:
total = 741.67
a = round(f(total), 2)
b = round(g(total), 2)
where f() and g() are the calculations used to split. Instead do this:
total = 741.67
a = round(f(total), 2)
b = total - a;
Now a + b are always equal to total.
However, you will never be able to get the starting value again when multiplying with 1.2 because of the rounding.
Related
My first idea was to make an array/list that has values assigned to each character.
So for example:
array[0] =' 0'
array[10] = 'A'
[...]
Then code would pick a random number y between [0,x] for slot 1.
For next slot [0,(x-y)] etc. When y <= 0 then fill rest of the slots with '0'.
Would that be enough for a simple voucher code generator? (It's not my decision to make encryption with this rule)
I am worried that sum of 9 is quite low for 6 character code, letters won't be used at all since they all have value over 9.
To prevent situation like this:
540000, 630000, 180000
Should I make chance of '0' to appear more?
What do you guys think about it?
Maybe you could also suggest some other way of doing this.
#Edit
Examples:
112320 = 1+1+2+3+2+0 = 9 Valid code, sum equals 9
000900 = 0+0+0+9+0+0 = 9 Valid code, sum equals 9
003015 = 0+0+3+0+1+5 = 9 Valid code, sum equals 9
A0012B = 10+0+0+1+2+11 = 24 Invalid code
Let's say that the function Rand(n) creates a random integer number that can go from 0 up to n (n included), then you can do the following:
Sum = 0;
A[0] = Rand(9);
Sum += A[0];
A[1] = Rand(9 - Sum);
Sum += A[1];
A[2] = Rand(9 - Sum);
Sum += A[2];
...
I just wrote this down very quickly, I didn't check the boundaries, but such an algorithm should do the trick.
I'm trying to figure out the name of the algorithm representing division operation as an array of integers you can summarize. Each element of this array must be as close to the actual rational result of the division as possible. For example:
5/2 = [3,2] (each element close to 2.5)
100/3 = [34,33,33] (each element close to 33.333(3))
3/1 = [3] (each element close to 3)
It seems like a very basic manipulation. The question is just out of sheer interest: is there a common name for such operation? Maybe it's already included in every math lib and I missed this fact?
Here's how I do it currently:
public IEnumerable<int> Distribute(int a, int b){
var div = a / b;
var rem = a % b;
return Enumerable.Repeat(div + 1, rem).Concat(Enumerable.Repeat(div, b - rem));
}
I think what you're looking for are the Math.Floor() and Math.Ceiling() functions. They can take a decimal number and return the highest (Math.Ceiling()) number and lowest (Math.Floor()) number closest to the decimal number given to those functions.
I'm having two CSV files where the first one looks like this:
ID Time PositionX PositionY
1 23
2 26
3 56
And another one that looks like this:
ID Time PositionX PositionY
25 2.5 5.5
28 4.1 5.6
35 4.8 6.2
66 5.5 7.5
The result that I want is:
ID Time PositionX PositionY
1 25(or 23) 2.5 5.5
2 28(or 26) 4.1 5.6
3 35(or 56) 4.8 6.2
So basically, I'm trying to merge two different files with different amount of data. But to combine them I need a key, the problem is that the key cannot be exactly the same for both of the data.
So I need to get Line by Line from one data set, see it's time, and see with the other dataset if there's a value close to this. If yes then merge them.
That's why I putted "25(or 23)" because the time is in milliseconds so I need to be sure that the line of the first dataset doesn't match with 28 but 25.
The final Key can be either 23 (from the first dataset) or 25 (from the second dataset). It doesn't matter as long as the line chosen is the closest to the value.
So I found out how to do it:
First I get the time of Dataset1:
String[] File1Rows = File.ReadAllLines(secondSensor.MyFile);
int number = Convert.ToInt32(File1Rows[1].Split(';')[0]);
Then create a list of strings made out of Dataset2:
String[] AccelerometerRows = File.ReadAllLines(fifthSensor.MyFile);
List<string> AccelerometterTimes = new List<string>(AccelerometerRows);
Then I take only the times in Dataset2 and put them into a list of strings
List<int> AccelerometterTimesList = new List<int>();
for (int i = 1; i < AccelerometterTimes.Count; i++)
{
var x = AccelerometerRows[i].Split(';')[0];
Console.WriteLine(x);
AccelerometterTimesList.Add(Convert.ToInt32(x));
}
Use a little bit of LinQ to get the closest value with O(n) complexity:
int closest = AccelerometterTimesList.Aggregate((x, y) => Math.Abs(x - number) < Math.Abs(y - number) ? x : y);
Then print it out:
Console.WriteLine("number: "+number);
Console.WriteLine("closest "+closest);
After this was found, now we use closest to get the line of Dataset2 that we need to get it's position. We take then the position, put them in the line of number from Dataset1.
I have the following code
int a = 1, n = 1;
Convert.ToInt32(a = a++ + n--);
Console.WriteLine("a: " + a + " n : " + n);
//If you debug the second line of the code in quick watch the answer is 3.
The answer to above code should be 2, so it is. But if i debug it and see the value in quickwatch the value of a is printed 3. Any idea why the same code results two different values.
Also note that the increment/decrement operators tailing the variables will be executed after the variable is used in the calculation (but before the result is written into a).
This will be interpreted as a= 1 +1, not a = 2 + 0
Specifcally the programm flows:
Take 1 out of 'a' into calculation memory.
Increment 'a' by 1
take 1 out of 'n' into calculation memory
Decrement 'n' by 1
Set 'a' to the sum of the two values you extracted earlier (not the current values of those variables)
Often putting seperate steps into seperate lines can yield a lot better debugging. i.e.:
I need to compare numeric data from two datatables with the same schema.
For example two tables with data such as
PKColumn | numCol | DecimalCol
will end up looking like this after the merge
PKColumn | numCol 1 | numCol 2 | numCol Diff | DecimalCol 1 | DecimalCol 2 | DecimalCol Diff
Initially, I just created the diff column as an expression col1-col2 but I can end up with unusual looking values
col1 col2 diff c1 c2 diff
12.8 14.6 -1.80000019 33.2 29.8 3.40000153
But what I want is:
col1 col2 diff c1 c2 diff
12.8 14.6 -1.8 33.2 29.8 3.4
So my current solution is to manually iterate through the rows and set the value using this method:
private static void SetDifference(DataRow dataRow, DataColumn numericColumn)
{
dynamic value1 = dataRow[numericColumn.Ordinal - 2];
dynamic value2 = dataRow[numericColumn.Ordinal - 1];
if (IsDbNullOrNullOrEmpty(value1) || IsDbNullOrNullOrEmpty(value2)) return;
//now find out the most decimals used and round to this value
string valueAsString = value1.ToString(CultureInfo.InvariantCulture);
int numOfDecimals = valueAsString.SkipWhile(c => c != '.').Skip(1).Count();
valueAsString = value2.ToString(CultureInfo.InvariantCulture);
numOfDecimals = System.Math.Max(numOfDecimals, valueAsString.SkipWhile(c => c != '.').Skip(1).Count());
double result = Convert.ToDouble(value1 - value2);
dataRow[numericColumn] = System.Math.Round(result, numOfDecimals);
}
But it feels clunky and not good for performance. Suggestions for improvements are welcome.
EDIT: changed column names from "int" to "num" to avoid confusion
EDIT: also, I don't always want to round to one decimal spot. I may have data like numA: 28 numB: 75.7999954 so I want a diff of: -47.7999954
If you have columns that store integer numbers then use an integer number type for them! Probably you used a single precision floating point type. The same holds for decimal types. Use a decimal column type for them and this rounding problem will vanish!
If you use a true decimal type (not float, single, real or double) you will not encounter rounding problems. I do not know which database you are using, but with SQL-Server the correct column type would be decimal.
UPDATE
Since you cannot change the column type, round it to the requested precision like this
result = Math.Round((c1-c2) * 10)/10; // One decimal
result = Math.Round((c1-c2) * 100)/100; // Two decimals
result = Math.Round((c1-c2) * 1000)/1000; // Three decimals
Math.Round(3.141592654 * 10000)/10000 ===> 3.1416
--
UPDATE
Try this, it should perform well in most cases
decimal result = (decimal)col1 - (decimal)col2;
Test
12.8f - 14.6f ===> -1.80000019
(decimal)12.8f - (decimal)14.6f ===> -1.8
Based on Olivier's comments I've updated my code to look like this:
if(numericColumn.DataType == typeof(int))
{
dataRow[numericColumn] = System.Math.Abs(value1 - value2);
}
else
{
dataRow[numericColumn] = Convert.ToDecimal(value1) - Convert.ToDecimal(value2);
}
Seems a lot cleaner and it gets the job done.
Thanks for the help.
You should do this in sql query using
ROUND(table1.IntCol 1 - table2.IntCol 2, 1)