C# 通过向列表中的最高或最低值项添加或减去1个单位进行舍入,直到行总数为100

C# 通过向列表中的最高或最低值项添加或减去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个单位,以此类推 我遇到了一些障碍,首先对数据表进行排序证明是个问题,因为我不知道列名等,所以我将其

我有一个预填充的数据表,该数据表中的每一行加起来需要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;a
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