C# 通过向列表中的最高或最低值项添加或减去1个单位进行舍入,直到行总数为100
我有一个预填充的数据表,该数据表中的每一行加起来需要100 我尝试使用这样的方法,如果行的总值小于100,我循环该行中的值,首先向最大值添加1个单位,检查是否达到100,如果没有,则向该行第二大值添加1个单位,依此类推 例如: 原始数据 50.2,40.6,9.0总计99.8 四舍五入后: 50.3,40.7,9.0总计100.0 如果行的总值大于100,则我希望重复此过程,但首先从最大值中删除1个单位,以此类推 我遇到了一些障碍,首先对数据表进行排序证明是个问题,因为我不知道列名等,所以我将其转换为数组 主要问题是,我无法让它在(inta=0;aC# 通过向列表中的最高或最低值项添加或减去1个单位进行舍入,直到行总数为100,c#,datatable,rounding,C#,Datatable,Rounding,我有一个预填充的数据表,该数据表中的每一行加起来需要100 我尝试使用这样的方法,如果行的总值小于100,我循环该行中的值,首先向最大值添加1个单位,检查是否达到100,如果没有,则向该行第二大值添加1个单位,依此类推 例如: 原始数据 50.2,40.6,9.0总计99.8 四舍五入后: 50.3,40.7,9.0总计100.0 如果行的总值大于100,则我希望重复此过程,但首先从最大值中删除1个单位,以此类推 我遇到了一些障碍,首先对数据表进行排序证明是个问题,因为我不知道列名等,所以我将其
private DataTable RoundingAndScaling(DataTable dtInput, int startingCol, int decPlaces = 1)
{
int dtRows = dtInput.Rows.Count;
int dtCols = dtInput.Columns.Count;
double temAdj;
double tempRowTotal;
int tempSig;
DataTable dtOuput = new DataTable();
dtOuput = dtInput.Copy();
DataTable dtFinal = new DataTable();
dtFinal = dtInput.Copy();
double[,] outputArray = new double[dtOuput.Columns.Count, 2];
for (int r = 0; r < dtRows - 1; r++)
{
tempRowTotal = 0;
for (int c = startingCol; c < dtCols; c++)
{
if (dtInput.Rows[r][c] == DBNull.Value)
{
dtOuput.Rows[r][c] = 0.0;
}
else
{
dtOuput.Rows[r][c] = Math.Round((double)dtInput.Rows[r][c], decPlaces);
}
outputArray[c - startingCol, 0] = Convert.ToDouble(dtOuput.Rows[r][c]);
tempRowTotal = tempRowTotal + Convert.ToDouble(dtOuput.Rows[r][c]);
}
//now check if that all the cells in that row = 100
if (tempRowTotal != 100)
{
tempSig = 1;
//Sort the data
double[,] arrayDb = new double[dtOuput.Columns.Count, 2];
arrayDb = SortArray(outputArray, dtCols);
//Find how many assets need to be adjusted by 1 unit
temAdj = (tempRowTotal - 1) * (10 ^ decPlaces); //10^
if (temAdj < 0)
{
temAdj = -1 * temAdj;
tempSig = -1;
}
//make the adjustment to the assets that have the largest holdings
for (int a = 0; a < temAdj; a++)
{
dtOuput.Rows[(int)(arrayDb[dtCols, 1])][1] = (int)dtOuput.Rows[(int)(arrayDb[dtCols, 1])][1] - tempSig * 1 / (10 ^ decPlaces); //^10
}
//get the data back into the correct structure to return
// for (int xx = 0; xx < dtCols; xx++)
// {
// dtFinal.Rows[dtRows][xx - 1] = dtOuput.Rows[xx][1];
// }
}
}
return dtOuput;
}
private double [,] SortArray(double [,] inData, int tempLen)
{
double temVal1;
double temVal2;
for (int i = 0; i < tempLen; i++)
{
for (int j = i + 1; j < tempLen; j++)
{
if (inData[i,0] > inData [j,0])
{
temVal1 = inData[i, 0];
temVal2 = inData [i,1];
inData [i,0] = inData [j,0];
inData[i,1] = inData [j,1];
inData[j, 0] = temVal1;
inData[j, 1] = temVal2;
}
}
}
return inData;
}
专用数据表取整和缩放(数据表dtInput,int startingCol,int deplaces=1)
{
int dtRows=dtInput.Rows.Count;
int dtCols=dtInput.Columns.Count;
双重变数;
双温全温;
int tempSig;
DataTable dtOuput=新的DataTable();
dtoutput=dtInput.Copy();
DataTable dtFinal=新DataTable();
dtFinal=dtInput.Copy();
double[,]outputArray=新的双精度[dtoutput.Columns.Count,2];
对于(int r=0;rinData[j,0])
{
temVal1=inData[i,0];
temVal2=inData[i,1];
inData[i,0]=inData[j,0];
inData[i,1]=inData[j,1];
inData[j,0]=temVal1;
inData[j,1]=temVal2;
}
}
}
返回inData;
}
就我个人而言,我对我的方法一点也不满意,而且我确信有一种更简单的方法来实现我正在尝试的目标,我会很高兴地抛弃上面的内容,转而采用更简单的方法:)非常感谢您的任何帮助。List numlist=new List();
List<decimal> numlist = new List<decimal>();
numlist.Add(50.2m);
numlist.Add(40.6m);
numlist.Add(9.0m);
decimal diff = 100.0m - numlist.Sum();
//This is set because the value should be only 1 decimal place
int update = Convert.ToInt32(diff / .1m);
if (update > 0)
{
for (int x = 0; x < update; x++)
{
numlist[x % numlist.Count()] += .1m;
}
}
else
{
for (int x = 0; x < Math.Abs(update); x++)
{
numlist[x % numlist.Count()] -= .1m;
}
}
添加的数字列表(50.2m);
numlist.Add(40.6m);
添加的数字列表(9.0m);
十进制差值=100.0m-numlist.Sum();
//之所以设置此值,是因为该值应仅为小数点后1位
int update=Convert.ToInt32(diff/.1m);
如果(更新>0)
{
对于(int x=0;x
为了提高精度,我使用了十进制,但下面是一些示例数据,用于获取差值,并尝试使其等于100%。(如果您超过100%,我也会输入代码,并且希望将其平均减少)如果有人对完成的代码感兴趣(这可能会帮助其他人),我将其粘贴在下面 我使用了Kevin Cook提供的代码,并根据我的需要进行了修改。在下面的示例中,您传入了一个数据表,其中包含希望查看的行和列。然后将其与数据的原始顺序一起写入列表。该列表按环绕的数字排序。然后运行舍入代码,一旦完成,列表将重新排序回其原始顺序。然后将其写回数据表并返回
private DataTable RoundScale(DataTable dtInput, int startingCol, int startingRow)
{
int xOrder = 0;
//write datatable values into a list (easier to work with)
for (int j = startingRow; j < dtInput.Rows.Count; j++)
{
List<SortingData> numlist = new List<SortingData>();
for (int iCol = startingCol; iCol < dtInput.Columns.Count; iCol++)
{
if ((dtInput.Rows[j][iCol] != DBNull.Value) && (Convert.ToDouble(dtInput.Rows[j][iCol]) != 0))
{
SortingData LSO = new SortingData
{
NumberToBeRounded = Convert.ToDecimal(Math.Round((double)dtInput.Rows[j][iCol], 1)),
OrderNum = xOrder
};
numlist.Add(LSO);
}
else
{
SortingData LSO_1 = new SortingData
{
NumberToBeRounded = Convert.ToDecimal(0.0),
OrderNum = xOrder
};
numlist.Add(LSO_1);
}
xOrder++;
}
//need to sort the list desc so unit is added to or removed from the largest item in the list first
numlist = numlist.OrderByDescending(o => o.NumberToBeRounded).ToList();
decimal numTotal = numlist.Sum(y => y.NumberToBeRounded);
if (numTotal != 0) //ignore if there are zero totals
{
decimal diff = 100.0m - numTotal;
//the value should be only 1 decimal place
int update = Convert.ToInt32(diff / .1m);
if (update > 0)
{
for (int x = 0; x < update; x++)
{
var sortednumlist = numlist[x % numlist.Count()];
sortednumlist.NumberToBeRounded += .1m;
}
}
else
{
for (int x = 0; x < Math.Abs(update); x++)
{
var sortednumlist = numlist[x % numlist.Count()];
sortednumlist.NumberToBeRounded -= .1m;
}
}
}
//change order of list back to original order
numlist = numlist.OrderBy(o => o.OrderNum).ToList();
//now write the list back into that datatable row
for (int i = startingCol; i < dtInput.Columns.Count; i++)
{
var numlistout = numlist[i - startingCol];
dtInput.Rows[j][i] = numlistout.NumberToBeRounded;
}
}
return dtInput;
}
public class SortingData
{
public decimal NumberToBeRounded { get; set; }
public int OrderNum { get; set; }
}
专用数据表圆形刻度(数据表dtInput、int startingCol、int startingRow)
{
int-xOrder=0;
//将数据表值写入列表(更易于使用)
对于(int j=startingRow;j