All Decimal numbers are rounded to 2 digits when saved into application. I'm given a number totalAmount and asked to divide it into n equal parts(or close to equal).
Example :
Given : totalAmount = 421.9720; count = 2 (totalAmount saved into application is 421.97)
Expected : 210.99, 210.98 => sum = 421.97
Actual(with plain divide) : 210.9860 (210.99), 210.9860 (210.99) => sum = 412.98
My approach :
var totalAmount = 421.972m;
var count = 2;
var individualCharge = Math.Floor(totalAmount / count);
var leftOverAmount = totalAmount - (individualCharge * count);
for(var i = 0;i < count; i++) {
Console.WriteLine(individualCharge + leftOverAmount);
leftOverAmount = 0;
}
This gives (-211.97, -210)
public IEnumerable<decimal> GetDividedAmounts(decimal amount, int count)
{
var pennies = (int)(amount * 100) % count;
var baseAmount = Math.Floor((amount / count) * 100) / 100;
foreach (var _ in Enumerable.Range(1, count))
{
var offset = pennies-- > 0 ? 0.01m : 0m;
yield return baseAmount + offset;
}
}
Feel free to alter this if you want to get an array or an IEnumerable which is not deferred. I updated it to get the baseAmount to be the floor value so it isn't recalculated within the loop.
Basically you need to find the base amount and a total of all the leftover pennies. Then, simply add the pennies back one by one until you run out. Because the pennies are based on the modulus operator, they'll always be in the range of [0, count - 1], so you'll never have a final leftover penny.
You're introducing a few rounding errors here, then compounding them. This is a common problem with financial data, especially when you have to constrain your algorithm to only produce outputs with 2 decimal places. It's worse when dealing with actual money in countries where 1 cent/penny/whatever coins are no longer legal tender. At least when working with electronic money the rounding isn't as big an issue.
The naive approach of dividing the total by the count and rounding the results is, as you've already discovered, not going to work. What you need is some way to spread out the errors while varying the output amounts by no more than $0.01. No output value can be more than $0.01 from any other output value, and the total must be the truncated total value.
What you need is a way to distribute the error across the output values, with the smallest possible variation between the values in the result. The trick is to track your error and adjust the output down once the error is high enough. (This is basically how the Bresenham line-drawing algorithm figures out when to increase the y value, if that helps.)
Here's the generalized form, which is pretty quick:
public IEnumerable<decimal> RoundedDivide(decimal amount, int count)
{
int totalCents = (int)Math.Floor(100 * amount);
// work out the true division, integer portion and error values
float div = totalCents / (float)count;
int portion = (int)Math.Floor(div);
float stepError = div - portion;
float error = 0;
for (int i = 0; i < count; i++)
{
int value = portion;
// add in the step error and see if we need to add 1 to the output
error += stepError;
if (error > 0.5)
{
value++;
error -= 1;
}
// convert back to dollars and cents for outputput
yield return value / 100M;
}
}
I've tested it with count values from 1 through 100, all outputs sum to match the (floored) input value exactly.
Try to break it down to steps:
int decimals = 2;
int factor = (int)Math.Pow(10, decimals);
int count = 2;
decimal totalAmount = 421.97232m;
totalAmount = Math.Floor(totalAmount * factor) / factor; // 421.97, you may want round here, depends on your requirement.
int baseAmount = (int)(totalAmount * factor / count); // 42197 / 2 = 21098
int left = (int)(totalAmount * factor) % count; // 1
// Adding back the left for Mod operation
for (int i = 0; i < left; i++)
{
Console.WriteLine((decimal)(baseAmount + 1) / factor); // 21098 + 1 / 100 = 210.99
}
// The reset that does not needs adjust
for (int i = 0; i < count - left; i++)
{
Console.WriteLine((decimal)baseAmount / factor); // 21098 / 100 = 210.98
}
If I have a double (234.004223), etc., I would like to round this to x significant digits in C#.
So far I can only find ways to round to x decimal places, but this simply removes the precision if there are any 0s in the number.
For example, 0.086 to one decimal place becomes 0.1, but I would like it to stay at 0.08.
The framework doesn't have a built-in function to round (or truncate, as in your example) to a number of significant digits. One way you can do this, though, is to scale your number so that your first significant digit is right after the decimal point, round (or truncate), then scale back. The following code should do the trick:
static double RoundToSignificantDigits(this double d, int digits){
if(d == 0)
return 0;
double scale = Math.Pow(10, Math.Floor(Math.Log10(Math.Abs(d))) + 1);
return scale * Math.Round(d / scale, digits);
}
If, as in your example, you really want to truncate, then you want:
static double TruncateToSignificantDigits(this double d, int digits){
if(d == 0)
return 0;
double scale = Math.Pow(10, Math.Floor(Math.Log10(Math.Abs(d))) + 1 - digits);
return scale * Math.Truncate(d / scale);
}
I've been using pDaddy's sigfig function for a few months and found a bug in it. You cannot take the Log of a negative number, so if d is negative the results is NaN.
The following corrects the bug:
public static double SetSigFigs(double d, int digits)
{
if(d == 0)
return 0;
decimal scale = (decimal)Math.Pow(10, Math.Floor(Math.Log10(Math.Abs(d))) + 1);
return (double) (scale * Math.Round((decimal)d / scale, digits));
}
It sounds to me like you don't want to round to x decimal places at all - you want to round to x significant digits. So in your example, you want to round 0.086 to one significant digit, not one decimal place.
Now, using a double and rounding to a number of significant digits is problematic to start with, due to the way doubles are stored. For instance, you could round 0.12 to something close to 0.1, but 0.1 isn't exactly representable as a double. Are you sure you shouldn't actually be using a decimal? Alternatively, is this actually for display purposes? If it's for display purposes, I suspect you should actually convert the double directly to a string with the relevant number of significant digits.
If you can answer those points, I can try to come up with some appropriate code. Awful as it sounds, converting to a number of significant digits as a string by converting the number to a "full" string and then finding the first significant digit (and then taking appropriate rounding action after that) may well be the best way to go.
If it is for display purposes (as you state in the comment to Jon Skeet's answer), you should use Gn format specifier. Where n is the number of significant digits - exactly what you are after.
Here is the the example of usage if you want 3 significant digits (printed output is in the comment of each line):
Console.WriteLine(1.2345e-10.ToString("G3"));//1.23E-10
Console.WriteLine(1.2345e-5.ToString("G3")); //1.23E-05
Console.WriteLine(1.2345e-4.ToString("G3")); //0.000123
Console.WriteLine(1.2345e-3.ToString("G3")); //0.00123
Console.WriteLine(1.2345e-2.ToString("G3")); //0.0123
Console.WriteLine(1.2345e-1.ToString("G3")); //0.123
Console.WriteLine(1.2345e2.ToString("G3")); //123
Console.WriteLine(1.2345e3.ToString("G3")); //1.23E+03
Console.WriteLine(1.2345e4.ToString("G3")); //1.23E+04
Console.WriteLine(1.2345e5.ToString("G3")); //1.23E+05
Console.WriteLine(1.2345e10.ToString("G3")); //1.23E+10
I found two bugs in the methods of P Daddy and Eric. This solves for example the precision error that was presented by Andrew Hancox in this Q&A. There was also a problem with round directions. 1050 with two significant figures isn't 1000.0, it's 1100.0. The rounding was fixed with MidpointRounding.AwayFromZero.
static void Main(string[] args) {
double x = RoundToSignificantDigits(1050, 2); // Old = 1000.0, New = 1100.0
double y = RoundToSignificantDigits(5084611353.0, 4); // Old = 5084999999.999999, New = 5085000000.0
double z = RoundToSignificantDigits(50.846, 4); // Old = 50.849999999999994, New = 50.85
}
static double RoundToSignificantDigits(double d, int digits) {
if (d == 0.0) {
return 0.0;
}
else {
double leftSideNumbers = Math.Floor(Math.Log10(Math.Abs(d))) + 1;
double scale = Math.Pow(10, leftSideNumbers);
double result = scale * Math.Round(d / scale, digits, MidpointRounding.AwayFromZero);
// Clean possible precision error.
if ((int)leftSideNumbers >= digits) {
return Math.Round(result, 0, MidpointRounding.AwayFromZero);
}
else {
return Math.Round(result, digits - (int)leftSideNumbers, MidpointRounding.AwayFromZero);
}
}
}
As Jon Skeet mentions: better handle this in the textual domain. As a rule: for display purposes, don't try to round / change your floating point values, it never quite works 100%. Display is a secondary concern and you should handle any special formatting requirements like these working with strings.
My solution below I implemented several years ago and has proven very reliable. It has been thoroughly tested and it performs quite well also. About 5 times longer in execution time than P Daddy / Eric's solution.
Examples of input + output given below in code.
using System;
using System.Text;
namespace KZ.SigDig
{
public static class SignificantDigits
{
public static string DecimalSeparator;
static SignificantDigits()
{
System.Globalization.CultureInfo ci = System.Threading.Thread.CurrentThread.CurrentCulture;
DecimalSeparator = ci.NumberFormat.NumberDecimalSeparator;
}
/// <summary>
/// Format a double to a given number of significant digits.
/// </summary>
/// <example>
/// 0.086 -> "0.09" (digits = 1)
/// 0.00030908 -> "0.00031" (digits = 2)
/// 1239451.0 -> "1240000" (digits = 3)
/// 5084611353.0 -> "5085000000" (digits = 4)
/// 0.00000000000000000846113537656557 -> "0.00000000000000000846114" (digits = 6)
/// 50.8437 -> "50.84" (digits = 4)
/// 50.846 -> "50.85" (digits = 4)
/// 990.0 -> "1000" (digits = 1)
/// -5488.0 -> "-5000" (digits = 1)
/// -990.0 -> "-1000" (digits = 1)
/// 0.0000789 -> "0.000079" (digits = 2)
/// </example>
public static string Format(double number, int digits, bool showTrailingZeros = true, bool alwaysShowDecimalSeparator = false)
{
if (Double.IsNaN(number) ||
Double.IsInfinity(number))
{
return number.ToString();
}
string sSign = "";
string sBefore = "0"; // Before the decimal separator
string sAfter = ""; // After the decimal separator
if (number != 0d)
{
if (digits < 1)
{
throw new ArgumentException("The digits parameter must be greater than zero.");
}
if (number < 0d)
{
sSign = "-";
number = Math.Abs(number);
}
// Use scientific formatting as an intermediate step
string sFormatString = "{0:" + new String('#', digits) + "E0}";
string sScientific = String.Format(sFormatString, number);
string sSignificand = sScientific.Substring(0, digits);
int exponent = Int32.Parse(sScientific.Substring(digits + 1));
// (the significand now already contains the requested number of digits with no decimal separator in it)
StringBuilder sFractionalBreakup = new StringBuilder(sSignificand);
if (!showTrailingZeros)
{
while (sFractionalBreakup[sFractionalBreakup.Length - 1] == '0')
{
sFractionalBreakup.Length--;
exponent++;
}
}
// Place decimal separator (insert zeros if necessary)
int separatorPosition = 0;
if ((sFractionalBreakup.Length + exponent) < 1)
{
sFractionalBreakup.Insert(0, "0", 1 - sFractionalBreakup.Length - exponent);
separatorPosition = 1;
}
else if (exponent > 0)
{
sFractionalBreakup.Append('0', exponent);
separatorPosition = sFractionalBreakup.Length;
}
else
{
separatorPosition = sFractionalBreakup.Length + exponent;
}
sBefore = sFractionalBreakup.ToString();
if (separatorPosition < sBefore.Length)
{
sAfter = sBefore.Substring(separatorPosition);
sBefore = sBefore.Remove(separatorPosition);
}
}
string sReturnValue = sSign + sBefore;
if (sAfter == "")
{
if (alwaysShowDecimalSeparator)
{
sReturnValue += DecimalSeparator + "0";
}
}
else
{
sReturnValue += DecimalSeparator + sAfter;
}
return sReturnValue;
}
}
}
Math.Round() on doubles is flawed (see Notes to Callers in its documentation). The later step of multiplying the rounded number back up by its decimal exponent will introduce further floating point errors in the trailing digits. Using another Round() as #Rowanto does won't reliably help and suffers from other problems. However if you're willing to go via decimal then Math.Round() is reliable, as is multiplying and dividing by powers of 10:
static ClassName()
{
powersOf10 = new decimal[28 + 1 + 28];
powersOf10[28] = 1;
decimal pup = 1, pdown = 1;
for (int i = 1; i < 29; i++) {
pup *= 10;
powersOf10[i + 28] = pup;
pdown /= 10;
powersOf10[28 - i] = pdown;
}
}
/// <summary>Powers of 10 indexed by power+28. These are all the powers
/// of 10 that can be represented using decimal.</summary>
static decimal[] powersOf10;
static double RoundToSignificantDigits(double v, int digits)
{
if (v == 0.0 || Double.IsNaN(v) || Double.IsInfinity(v)) {
return v;
} else {
int decimal_exponent = (int)Math.Floor(Math.Log10(Math.Abs(v))) + 1;
if (decimal_exponent < -28 + digits || decimal_exponent > 28 - digits) {
// Decimals won't help outside their range of representation.
// Insert flawed Double solutions here if you like.
return v;
} else {
decimal d = (decimal)v;
decimal scale = powersOf10[decimal_exponent + 28];
return (double)(scale * Math.Round(d / scale, digits, MidpointRounding.AwayFromZero));
}
}
}
I agree with the spirit of Jon's assessment:
Awful as it sounds, converting to a number of significant digits as a string by converting the number to a "full" string and then finding the first significant digit (and then taking appropriate rounding action after that) may well be the best way to go.
I needed significant-digit rounding for approximate and non-performance-critical computational purposes, and the format-parse round-trip through "G" format is good enough:
public static double RoundToSignificantDigits(this double value, int numberOfSignificantDigits)
{
return double.Parse(value.ToString("G" + numberOfSignificantDigits));
}
This question is similiar to the one you're asking:
Formatting numbers with significant figures in C#
Thus you could do the following:
double Input2 = 234.004223;
string Result2 = Math.Floor(Input2) + Convert.ToDouble(String.Format("{0:G1}", Input2 - Math.Floor(Input2))).ToString("R6");
Rounded to 1 significant digit.
Let inputNumber be input that needs to be converted with significantDigitsRequired after decimal point, then significantDigitsResult is the answer to the following pseudo code.
integerPortion = Math.truncate(**inputNumber**)
decimalPortion = myNumber-IntegerPortion
if( decimalPortion <> 0 )
{
significantDigitsStartFrom = Math.Ceil(-log10(decimalPortion))
scaleRequiredForTruncation= Math.Pow(10,significantDigitsStartFrom-1+**significantDigitsRequired**)
**siginficantDigitsResult** = integerPortion + ( Math.Truncate (decimalPortion*scaleRequiredForTruncation))/scaleRequiredForTruncation
}
else
{
**siginficantDigitsResult** = integerPortion
}
Tested on .NET 6.0
In my opinion, the rounded results are inconsistent due to the defects of the framework and the error of the floating point. Therefore, be careful about use.
decimal.Parse(doubleValue.ToString("E"), NumberStyles.Float);
example:
using System.Diagnostics;
using System.Globalization;
List<double> doubleList = new();
doubleList.Add( 0.012345);
doubleList.Add( 0.12345 );
doubleList.Add( 1.2345 );
doubleList.Add( 12.345 );
doubleList.Add( 123.45 );
doubleList.Add( 1234.5 );
doubleList.Add(12345 );
doubleList.Add(10 );
doubleList.Add( 0 );
doubleList.Add( 1 );
doubleList.Add(-1 );
doubleList.Add( 0.1);
Debug.WriteLine("");
foreach (var item in doubleList)
{
Debug.WriteLine(decimal.Parse(item.ToString("E2"), NumberStyles.Float));
// 0.0123
// 0.123
// 1.23
// 12.3
// 123
// 1230
// 12300
// 10.0
// 0.00
// 1.00
// -1.00
// 0.100
}
Debug.WriteLine("");
foreach (var item in doubleList)
{
Debug.WriteLine(decimal.Parse(item.ToString("E3"), NumberStyles.Float));
// 0.01235
// 0.1235
// 1.234
// 12.35
// 123.5
// 1234
// 12340
// 10.00
// 0.000
// 1.000
// -1.000
// 0.1000
}
As pointed out by #Oliver Bock is that Math.Round() on doubles is flawed (see Notes to Callers in its documentation). The later step of multiplying the rounded number back up by its decimal exponent will introduce further floating point errors in the trailing digits. Generally, any multiplication by or division by a power of ten gives a non-exact result, since floating-point is typically represented in binary, not in decimal.
Using the following function will avoid floating point errors in the trailing digits:
static double RoundToSignificantDigits(double d, int digits)
{
if (d == 0.0 || Double.IsNaN(d) || Double.IsInfinity(d))
{
return d;
}
// Compute shift of the decimal point.
int shift = digits - 1 - (int)Math.Floor(Math.Log10(Math.Abs(d)));
// Return if rounding to the same or higher precision.
int decimalPlaces = 0;
for (long pow = 1; Math.Floor(d * pow) != (d * pow); pow *= 10) decimalPlaces++;
if (shift >= decimalPlaces)
return d;
// Round to sf-1 fractional digits of normalized mantissa x.dddd
double scale = Math.Pow(10, Math.Abs(shift));
return shift > 0 ?
Math.Round(d * scale, MidpointRounding.AwayFromZero) / scale :
Math.Round(d / scale, MidpointRounding.AwayFromZero) * scale;
}
However if you're willing to go via decimal then Math.Round() is reliable, as is multiplying and dividing by powers of 10:
static double RoundToSignificantDigits(double d, int digits)
{
if (d == 0.0 || Double.IsNaN(d) || Double.IsInfinity(d))
{
return d;
}
decimal scale = (decimal)Math.Pow(10, Math.Floor(Math.Log10(Math.Abs(d))) + 1);
return (double)(scale * Math.Round((decimal)d / scale, digits, MidpointRounding.AwayFromZero));
}
Console.WriteLine("{0:G17}", RoundToSignificantDigits(5.015 * 100, 15)); // 501.5
for me, this one works pretty fine and is also valid for negative numbers:
public static double RoundToSignificantDigits(double number, int digits)
{
int sign = Math.Sign(number);
if (sign < 0)
number *= -1;
if (number == 0)
return 0;
double scale = Math.Pow(10, Math.Floor(Math.Log10(Math.Abs(number))) + 1);
return sign * scale * Math.Round(number / scale, digits);
}
My solution may be helpful in some cases, I use it to display crypto prices which vary greatly in magnitude - it always gives me a specified number of significant figures but unlike ToString("G[number of digits]") it doesn't show small values in scientific notation (don't know a way to avoid this with ToString(), if there is then please let me know!)
const int MIN_SIG_FIGS = 6; //will be one more for < 0
int numZeros = (int)Math.Floor(Math.Log10(Math.Abs(price))); //get number of zeros before first digit, will be negative for price > 0
int decPlaces = numZeros < MIN_SIG_FIGS
? MIN_SIG_FIGS - numZeros < 0
? 0
: MIN_SIG_FIGS - numZeros
: 0; //dec. places: set to MIN_SIG_FIGS + number of zeros, unless numZeros greater than sig figs then no decimal places
return price.ToString($"F{decPlaces}");
Here's a version inspired by Peter Mortensen that adds a couple of safeguards for edge cases such as value being NaN, Inf or very small:
public static double RoundToSignificantDigits(this double value, int digits)
{
if (double.IsNaN(value) || double.IsInfinity(value))
return value;
if (value == 0.0)
return 0.0;
double leftSideNumbers = Math.Floor(Math.Log10(Math.Abs(value))) + 1;
int places = digits - (int)leftSideNumbers;
if (places > 15)
return 0.0;
double scale = Math.Pow(10, leftSideNumbers);
double result = scale * Math.Round(value / scale, digits, MidpointRounding.AwayFromZero);
if (places < 0)
places = 0;
return Math.Round(result, places, MidpointRounding.AwayFromZero);
}
I just did:
int integer1 = Math.Round(double you want to round,
significant figures you want to round to)
Here is something I did in C++
/*
I had this same problem I was writing a design sheet and
the standard values were rounded. So not to give my
values an advantage in a later comparison I need the
number rounded, so I wrote this bit of code.
It will round any double to a given number of significant
figures. But I have a limited range written into the
subroutine. This is to save time as my numbers were not
very large or very small. But you can easily change that
to the full double range, but it will take more time.
Ross Mckinstray
rmckinstray01#gmail.com
*/
#include <iostream>
#include <fstream>
#include <string>
#include <math.h>
#include <cmath>
#include <iomanip>
#using namespace std;
double round_off(double input, int places) {
double roundA;
double range = pow(10, 10); // This limits the range of the rounder to 10/10^10 - 10*10^10 if you want more change range;
for (double j = 10/range; j< 10*range;) {
if (input >= j && input < j*10){
double figures = pow(10, places)/10;
roundA = roundf(input/(j/figures))*(j/figures);
}
j = j*10;
}
cout << "\n in sub after loop";
if (input <= 10/(10*10) && input >= 10*10) {
roundA = input;
cout << "\nDID NOT ROUND change range";
}
return roundA;
}
int main() {
double number, sig_fig;
do {
cout << "\nEnter number ";
cin >> number;
cout << "\nEnter sig_fig ";
cin >> sig_fig;
double output = round_off(number, sig_fig);
cout << setprecision(10);
cout << "\n I= " << number;
cout << "\n r= " <<output;
cout << "\nEnter 0 as number to exit loop";
}
while (number != 0);
return 0;
}
Hopefully I did not change anything formatting it.
Assuming there's a float number with 7 digits how to find the smallest number that can be added to that float?
Example 1: 1234.567f + 0000.001f = 1234.568f
Example 2: 0.01234567 + 0.00000001f = 0.01234568f
OP added C# after posting of this C answer.
Will leave this C solution up as a reference.
Print the number out in exponential format and change each digit, to '0' or '1'
float smallest_float_summable(float f, int digs) {
char buf[20];
sprintf(buf, "%.*e", digs - 1, f);
char *p = buf;
while (*p != 'e') {
if (isdigit(*p)) {
*p = '0' + (p[1] == 'e');
}
p++;
}
float y;
sscanf(buf, "%e", &y);
return y;
}
printf("%e\n", smallest_float_summable(1234.567f, 7));
// 1.000000e-03
This will not get the smallest as the typically a number near 1/2 the value of smallest_float_summable() will effect the change, yet this seems to match OP's intent.
To get the smallest number that will effect some change, simple use nextafter()
The nextafter functions determine the next representable value, in the type of the function, after x in the direction of y ... C11dr ยง7.12.11.3 2
#include <math.h>
float smallest_change(float f) {
float dif = f - nextafterf(f, 0);
return dif;
}
[Edit]
#aka.nice correctly points out that even smaller, maybe about 1/2 dif will effect a change. Will ponder this.
To find the smallest epsilon, you could start with 10eN where N is 1, and move down to a smaller number and add it. Then compare it to the original number.
number = x
N = 1
newnumber = 3
while (number <> newnumber){
newnumber = (number + 10eN)
N = N - 1
}
Then 10e(N+1) is the smallest epsilon.
I have the following code to divide an amount by a number and allocate the result as an amount that needs to be paid per month.
objData.month_per_amount = (Convert.ToDecimal(txtAmount.Value) / Convert.ToInt32(txtMonths.Value));
In a scenario example if I divide 13 by 3 and round off the result to 2 decimal places I get 4.33 for each month. But when I multiply 4.33 by 3 I am getting 12.99, which is not equivalent to 13. There is a discrepancy of 0.01. In this scenario how can I allocate like below:
month 1: 4.33
month 2: 4.33
month 3: 4.34
Hope I made it clear, the preferred code should only be executed if there is such a discrepancy, for example if 14 is to be divided by 2, we get 7 for each month and 7+7=14, so exactly the same figure we are getting here.
In accounting you'd often use something called 'reducing balance' for this. The idea is that you calculate the month's total, deduct it from the overall total and reduce the number of months. So something like:
decimal balance = 13m;
int months = 3;
int monthsRemaining = 3;
for (var i = 0; i < months; i++)
{
decimal thisMonth = Math.Round(balance / monthsRemaining, 2);
balance -= thisMonth;
monthsRemaining -= 1;
Console.WriteLine("Month {0}: {1}", i + 1, thisMonth);
}
This will result in 4.33, 4.34, 4.33.
The benefit of this method is that the rounding errors are distributed fairly evenly throughout the period rather than all in one month. For example, 100 over 24 months using that method would result in 23 payments of 4.17 and 1 of 4.09 whereas reducing balance would be 4.16 or 4.17 each month.
You do not have to check the remainder. A more efficient C# code (in terms of the required computation) would be like the following.
double amount = 13;
int months = 3;
int precision = 2;
double[] amountForEachMonth = new double[months];
double temp = Math.Round(amount / months, precision);
for (int i = 0 ; i < months - 1 ; i++)
amountForEachMonth[i] = temp;
amountForEachMonth[months - 1] = amount - (temp * (months - 1)) ;
You don't need to make it a special case when there is a discrepancy, you can simply always calculate the payment of the last month as what's left to pay to reach the total amount. If there is no discrepancy then it will be the same value anyway. Example:
int months = Convert.ToInt32(txtMonths.Value);
decimal amount = Convert.ToDecimal(txtAmount.Value);
month_per_amount = Decimal.Round(amount / months, 2);
decimal last_month = amount - (months - 1) * month_per_amount;
for (int month = 1; month <= months; month++) {
decimal monthly = month < months ? month_per_amount : last_month;
Console.WriteLine("Month {0}: {1}", month, monthly);
}
if " amount % month == 0 " , no discrepancy occures. otherwise, the last item should be a little more than others .
(The code here may have some syntax issues, I wanted to show you the algorithm.)
decimal amount = Convert.ToDecimal(txtAmount.Value);
int month = Convert.ToInt32(txtMonths.Value);
int n = 3;
decimal amounts[3];//n = 3
for (int i = 0 ; i < n-1 ; i++)
amounts[i] = amount / month;
if ( amount % month != 0 ) {
amounts[n-1] = amount - ( amount / month * (n-1) ) ;
else
amounts[n-1] = amount / month ;