Hello everyone,
Here is my simple bonus assignment program. The issue I met with is, the ResultTotalReceived is larger then ResultTotalSent, which violates corporation policy and exception is thrown.
The program works in this way,
1. At source side, calculate and assign the bonus according to each worker's factor (100F for worker1 and 300F for worker2 in my sample). All figures are float type.
2. Convert the float type to string and sent to another destination to store the bonus into storage;
3. The detination side will perform basic checking rules before storing the data, e.g. the total bonus assigned should not exceed the total bonus available at source side.
In my code below,
The value of ResultTotalSent is 199.321, and the value of ResultTotalReceived is 199.321045, which is larger than ResultTotalSent.
My questions is,
1. If I want to solve this issue at source side, what is the elegant way to solve this issue? Currently, my temp solution is using ToString("F2"). Any issues with this solution?
2. Why there is such issue? It is the issue of ToString of Float class -- I have this suspecision is because ResultTotalSent is precise but after ToString conversion the result and conversion back at detination side, it is not precise?
[Code]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestFloat
{
class Program
{
static void Main(string[] args)
{
float TotalBonus = 199.321F;
float Worker1 = 100F;
float Worker2 = 300F;
float Result1 = TotalBonus * Worker1 / (Worker1 + Worker2);
float Result2 = TotalBonus * Worker2 / (Worker1 + Worker2);
float ResultTotalSent = Result1 + Result2;
string Result1String = Result1.ToString();
string Result2String = Result2.ToString();
// sending to another computer using string
// received from another computer using string
string ReceivedString1 = Result1String;
string ReceivedString2 = Result2String;
float Received1 = float.Parse(ReceivedString1);
float Received2 = float.Parse(ReceivedString2);
float ResultTotalReceived = Received1 + Received2;
// sanity checking failed, since ResultTotalReceived > TotalBonus
return;
}
}
}
[/Code]
thanks in advance,
George
George GeorgePosted May 29, 2008, 1:41 AM
Thanks SB Chatterjee,
I re-studied my code again. My question is, it seems the ToString method did rounding for string Result2String = Result2.ToString(), but no rounding for string Result1String = Result1.ToString(). Do you know what is the root cause?
[Code]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestFloat
{
class Program
{
static void Main(string[] args)
{
float TotalBonus = 199.321F;
float Worker1 = 100F;
float Worker2 = 300F;
float Result1 = TotalBonus * Worker1 / (Worker1 + Worker2);
float Result2 = TotalBonus * Worker2 / (Worker1 + Worker2);
float ResultTotalSent = Result1 + Result2;
string Result1String = Result1.ToString();
string Result2String = Result2.ToString();
// sending to another computer using string
// received from another computer using string
string ReceivedString1 = Result1String;
string ReceivedString2 = Result2String;
float Received1 = float.Parse(ReceivedString1);
float Received2 = float.Parse(ReceivedString2);
float ResultTotalReceived = Received1 + Received2;
// sanity checking failed, since ResultTotalReceived > TotalBonus
if ((ResultTotalReceived - ResultTotalSent) < float.Epsilon)
{
// not executed here
Console.WriteLine("Treated the same. ");
}
}
}
}
[/Code]
regards,
George
SB ChatterjeePosted May 28, 2008, 10:21 PM
For example, see Convert.ToString Method (Single, IFormatProvider)
http://msdn.microsoft.com/en-us/library/ms131016(VS.80).aspx
For Double -
http://msdn.microsoft.com/en-us/library/ms131010(VS.80).aspx
Based on the precision required (for the calculations) - one can choose the type (single, double, etc).
SB Chatterjee
George GeorgePosted May 26, 2008, 8:54 PM
Thanks SB Chatterjee,
Really great reply!
My further concerns after study,
1. Is the root cause ToString method or data type (float type and its representation)? I suspect it is the ToString method, which increases one float number into string representation, and keep the other float number the same into string representation, so the result is larger than before. Any comments?
(you can debug my code and see using pure float data type calculation is always fine, but when ToString and convert back to float, the precise is losing.)
2. Why using larger size data type could solve this issue -- for example decimal? If ToString method still has the issue mentioned in (1), even if using larger data type size, the issue stil exists. Any comments?
regards,
George
SB ChatterjeePosted May 26, 2008, 7:04 PM
See here for more details -
http://msdn.microsoft.com/en-us/library/c151dt3s(VS.80).aspx
SBC