|
ms
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Why there are two diffrent result in two almost same formula-------- static void Main(string[] args) { int num = 3600; Single XNT = 0.3F; Single SX = 1546.08594F; Single result = (XNT * num) / SX; Single result2 = System.Convert.ToSingle(XNT * num) / SX; System.Console.WriteLine(result); System.Console.WriteLine(result2); return; } -------- The result is "0.6985382", but the result2 is "0.6985381". Why there are two diffrent result here? When "XNT * num", because "XNT" is the type of Single, I think the system should automatic convert the result to Single. But when I manually add the "System.Convert.ToSingle()", the diffrent result appeared. Any idea? Thank you!
Show quote
Hide quote
> Hi everyone. My source code is the following in VS2005: Additional:> > -------- > static void Main(string[] args) > { > int num = 3600; > Single XNT = 0.3F; > Single SX = 1546.08594F; > > Single result = (XNT * num) / SX; > Single result2 = System.Convert.ToSingle(XNT * num) / SX; > > System.Console.WriteLine(result); > System.Console.WriteLine(result2); > return; > } > -------- > > The result is "0.6985382", but the result2 is "0.6985381". > Why there are two diffrent result here? > > When "XNT * num", because "XNT" is the type of Single, I think the system should > automatic convert the result to Single. But when I manually add the > "System.Convert.ToSingle()", the diffrent result appeared. Any idea? > > Thank you! I just changed the variable "num" from int to Single. But I was shocked that the two result is also diffrent. (XNT * num) / SX -> 0.6985382 System.Convert.ToSingle(XNT * num) / SX -> 0.6985381 How? It confuse me very much... On Wed, 10 Jun 2009 01:16:40 -0700, XjAcKs <xja***@gmail.com> wrote:
Show quoteHide quote > [...] I haven't had a chance to verify your results. I do agree that, assuming >> When "XNT * num", because "XNT" is the type of Single, I think the >> system should >> automatic convert the result to Single. But when I manually add the >> "System.Convert.ToSingle()", the diffrent result appeared. Any idea? >> >> Thank you! > > Additional: > > I just changed the variable "num" from int to Single. But I was shocked > that the > two result is also diffrent. > (XNT * num) / SX -> 0.6985382 > System.Convert.ToSingle(XNT * num) / SX -> 0.6985381 > > How? It confuse me very much... the code actually does what you say it does, there's something odd going on. But, I should point out that whatever is going on, it's not a question of whether or not the "system should automatically convert the results to Single". The type of the expression "XNT * num" _is_ definitely Single. The only other implicit conversion that would even be allowed is Double, and a) that won't happen because there's no Double in the expression, and b) if it did happen, you'd be unable to assign the final result to a variable of type Single, because the whole expression would have wound up as a Double and an implicit conversion from Double back to Single isn't allowed (i.e. you would've had to put a cast, if the expression wasn't being done as a Single in the first place, so it must be getting evaluated as Single). The thing that's weird is that the calculation is being performed differently, independent of the precision (which must be the same in either case), depending on context. I don't have time to look at it now, and maybe by the time I do, someone else will have already figured it out. But, one would expect that "XNT * num" would always produce the same value, and that for a given value, dividing by "SX" would also always produce the same value. The only explanation for what you're seeing is that somewhere in there is an incorrect assumption. To me, the most obvious suspect is the Convert.ToSingle() method, but the documentation claims that Convert.ToSingle(Single) always returns exactly the value that was passed to it. And given all that, the most obviously explanation I see is that there's a compiler bug that is either choosing the wrong overload for the ToSingle() method (i.e. using ToSingle(Double), which could produce a subtle difference in the result), or is actually generating different IL simply because of the presence of the method call. There is a more remote possibility that the ToSingle(Single) method does not in fact do what the documentation says it does. In the meantime, you can look into those theories yourself if you like. ILDASM.EXE can show you the IL generated in your program, where you can look for specific differences in the code the compiler generates (i.e. differences in the calculations, or using a different method overload than one would expect given the code). To check to see what ToSingle(Single) does, you'll either need to use Red Gate's Reflector (Google it) or configure your IDE to download the .NET source while debugging, and then step into the method. I'm curious myself, so if there's not an answer twelve hours or so from now (when I'll actually have time to look at it myself), I'll see what I can figure out. Finally, note that if it is a bug, it's possible it's been fixed since ..NET 2.0/VS 2005 (depending on whether it's a framework or compiler bug). I'm only going to be able to test the code with .NET 3.5/VS 2008 at the moment, so one thing you might want to do is try to test it yourself on a more recent compiler and/or .NET version and see if it still happens. That would be a very useful data point. Pete
Show quote
Hide quote
> On Wed, 10 Jun 2009 01:16:40 -0700, XjAcKs <xja***@gmail.com> wrote: Thanks for you reply. My english is poor, so I will have to read your reply for > >> [...] >>> When "XNT * num", because "XNT" is the type of Single, I think the >>> system should >>> automatic convert the result to Single. But when I manually add the >>> "System.Convert.ToSingle()", the diffrent result appeared. Any idea? >>> >>> Thank you! >> >> Additional: >> >> I just changed the variable "num" from int to Single. But I was >> shocked that the >> two result is also diffrent. >> (XNT * num) / SX -> 0.6985382 >> System.Convert.ToSingle(XNT * num) / SX -> 0.6985381 >> >> How? It confuse me very much... > > I haven't had a chance to verify your results. I do agree that, > assuming the code actually does what you say it does, there's something > odd going on. > >... > > Finally, note that if it is a bug, it's possible it's been fixed since > .NET 2.0/VS 2005 (depending on whether it's a framework or compiler > bug). I'm only going to be able to test the code with .NET 3.5/VS 2008 > at the moment, so one thing you might want to do is try to test it > yourself on a more recent compiler and/or .NET version and see if it > still happens. That would be a very useful data point. > > Pete a while. If I find out something later, I will send a reply. BTW: I just try the program in .NET 3.5/VS 2008, and the result the same as .NET 2.0/VS 2005, so I think it seems not a complier bug or it haven't been fixed.
Show quote
Hide quote
> I just try my code in Java language, and the expression's result is the same >> On Wed, 10 Jun 2009 01:16:40 -0700, XjAcKs <xja***@gmail.com> wrote: >> >>> [...] >>>> When "XNT * num", because "XNT" is the type of Single, I think the >>>> system should >>>> automatic convert the result to Single. But when I manually add the >>>> "System.Convert.ToSingle()", the diffrent result appeared. Any idea? >>>> >>>> Thank you! >>> >>> Additional: >>> >>> I just changed the variable "num" from int to Single. But I was >>> shocked that the >>> two result is also diffrent. >>> (XNT * num) / SX -> 0.6985382 >>> System.Convert.ToSingle(XNT * num) / SX -> 0.6985381 >>> >>> How? It confuse me very much... >> >> I haven't had a chance to verify your results. I do agree that, >> assuming the code actually does what you say it does, there's >> something odd going on. >> >> ... >> >> Finally, note that if it is a bug, it's possible it's been fixed since >> .NET 2.0/VS 2005 (depending on whether it's a framework or compiler >> bug). I'm only going to be able to test the code with .NET 3.5/VS >> 2008 at the moment, so one thing you might want to do is try to test >> it yourself on a more recent compiler and/or .NET version and see if >> it still happens. That would be a very useful data point. >> >> Pete > > Thanks for you reply. My english is poor, so I will have to read your > reply for a while. If I find out something later, I will send a reply. > > BTW: I just try the program in .NET 3.5/VS 2008, and the result the same > as .NET 2.0/VS 2005, so I think it seems not a complier bug or it > haven't been fixed. value: 0.6985381. So I think the expression with ToSingle() method is right... >> Thanks for you reply. My english is poor, so I will have to read your I think I have figured out out.>> reply for a while. If I find out something later, I will send a reply. >> >> BTW: I just try the program in .NET 3.5/VS 2008, and the result the >> same as .NET 2.0/VS 2005, so I think it seems not a complier bug or it >> haven't been fixed. > > I just try my code in Java language, and the expression's result is the > same value: 0.6985381. So I think the expression with ToSingle() method > is right... I changed the variables definition "result" and "result2" to Double and I delete the "SX" in expression. And it is : int num = 3600; Single XNT = 0.3F; Double result = XNT * num ; Double result2 = System.Convert.ToSingle(XNT * num); And, the value of two result is: result -> 1080.00004291534 result2 -> 1080 It seems that Single is more better than Double here...
Show quote
Hide quote
>>> Thanks for you reply. My english is poor, so I will have to read your Single result = (XNT * num) / SX;>>> reply for a while. If I find out something later, I will send a reply. >>> >>> BTW: I just try the program in .NET 3.5/VS 2008, and the result the >>> same as .NET 2.0/VS 2005, so I think it seems not a complier bug or >>> it haven't been fixed. >> >> I just try my code in Java language, and the expression's result is >> the same value: 0.6985381. So I think the expression with ToSingle() >> method is right... > > I think I have figured out out. > I changed the variables definition "result" and "result2" to Double and > I delete the "SX" in expression. And it is : > > int num = 3600; > Single XNT = 0.3F; > Double result = XNT * num ; > Double result2 = System.Convert.ToSingle(XNT * num); > > And, the value of two result is: > result -> 1080.00004291534 > result2 -> 1080 > > It seems that Single is more better than Double here... Single result2 = System.Convert.ToSingle(XNT * num) / SX; So I think in the first expression, the result of "XNT * num" is a type of Double. But why one Single variable multiply another Single variable, the result is a type of Double? How weird it is... What happens if you change
Single result2 = System.Convert.ToSingle(XNT * num) / SX; to Single result2 = System.Convert.ToSingle((XNT * num) / SX); ? First one, you are modifying the left side before dividing. Second one, you are modifying the result. I would suggest the second one would be correct. -- Show quoteHide quoteBest regards, Dave Colliver. http://www.AshfieldFOCUS.com ~~ http://www.FOCUSPortals.com - Local franchises available "XjAcKs" <xja***@gmail.com> wrote in message news:eb4IoIb6JHA.5756@TK2MSFTNGP02.phx.gbl... >>>> Thanks for you reply. My english is poor, so I will have to read your >>>> reply for a while. If I find out something later, I will send a reply. >>>> >>>> BTW: I just try the program in .NET 3.5/VS 2008, and the result the >>>> same as .NET 2.0/VS 2005, so I think it seems not a complier bug or it >>>> haven't been fixed. >>> >>> I just try my code in Java language, and the expression's result is the >>> same value: 0.6985381. So I think the expression with ToSingle() method >>> is right... >> >> I think I have figured out out. >> I changed the variables definition "result" and "result2" to Double and I >> delete the "SX" in expression. And it is : >> >> int num = 3600; >> Single XNT = 0.3F; >> Double result = XNT * num ; >> Double result2 = System.Convert.ToSingle(XNT * num); >> >> And, the value of two result is: >> result -> 1080.00004291534 >> result2 -> 1080 >> >> It seems that Single is more better than Double here... > > Single result = (XNT * num) / SX; > Single result2 = System.Convert.ToSingle(XNT * num) / SX; > > So I think in the first expression, the result of "XNT * num" is a type of > Double. > > But why one Single variable multiply another Single variable, the result > is a type of Double? How weird it is...
Show quote
Hide quote
> What happens if you change After did the change you said, the result is "0.6985382", the same value as the > > Single result2 = System.Convert.ToSingle(XNT * num) / SX; > > to > > Single result2 = System.Convert.ToSingle((XNT * num) / SX); > > > ? > > First one, you are modifying the left side before dividing. Second one, you > are modifying the result. I would suggest the second one would be correct. > expression without ToSingle(). But if I use calculator program of WindowsXP and manually input the formula "(0.3 * 3600) / 1546.08594", the result is "0.69853814206472895031954045193633", so I think it is correct modifying the left side before dividing by ToSingle(). On Wed, 10 Jun 2009 03:00:49 -0700, XjAcKs <xja***@gmail.com> wrote:
> Single result = (XNT * num) / SX; That depends on what you mean by "is a type of Double".> Single result2 = System.Convert.ToSingle(XNT * num) / SX; > > So I think in the first expression, the result of "XNT * num" is a type > of Double. Looking at the replies from Hans, I suspect that the difference can be explained by the compiler using storage of precision Double to do the calculation. But, the expression is most definitely _not_ literally typed as Double; there are very specific type conversion rules in C# that would preclude treating the expression that way. > But why one Single variable multiply another Single variable, the result As Hans says, it may be more efficient to do the calculation using a > is a type of Double? How weird it is... higher-precision storage, effectively promoting the values to Double temporarily during the calculation. Because the semantic type of the expression remains Single though, the compiler will wind up converting the result back to Single when storing it. In the code you posted, assuming this behavior (I still don't have time to go check everything myself), that would readily explain why you get different results depending on at what step you force the conversion back to Single. When you call Convert.ToSingle(), that forces the conversion to happen immediately after the multiplication. When you don't, then the conversion can be delayed until after the division. The potential for that to produce different results is obvious. Pete
Show quote
Hide quote
> That depends on what you mean by "is a type of Double". By do some experiment and read your reply, finally I understood the reason why > > Looking at the replies from Hans, I suspect that the difference can be > explained by the compiler using storage of precision Double to do the > calculation. But, the expression is most definitely _not_ literally > typed as Double; there are very specific type conversion rules in C# > that would preclude treating the expression that way. > >> But why one Single variable multiply another Single variable, the >> result is a type of Double? How weird it is... > > As Hans says, it may be more efficient to do the calculation using a > higher-precision storage, effectively promoting the values to Double > temporarily during the calculation. Because the semantic type of the > expression remains Single though, the compiler will wind up converting > the result back to Single when storing it. > > In the code you posted, assuming this behavior (I still don't have time > to go check everything myself), that would readily explain why you get > different results depending on at what step you force the conversion > back to Single. When you call Convert.ToSingle(), that forces the > conversion to happen immediately after the multiplication. When you > don't, then the conversion can be delayed until after the division. The > potential for that to produce different results is obvious. > > Pete the problem happend. Pete, Hans, Thank you very much! It's very helpful. XjAcKs On Jun 10, 5:52 pm, XjAcKs <xja***@gmail.com> wrote:
Show quoteHide quote > >> Thanks for you reply. My english is poor, so I will have to read your I believe this is a wrong conclusion.> >> reply for a while. If I find out something later, I will send a reply. > > >> BTW: I just try the program in .NET 3.5/VS 2008, and the result the > >> same as .NET 2.0/VS 2005, so I think it seems not a complier bug or it > >> haven't been fixed. > > > I just try my code in Java language, and the expression's result is the > > same value: 0.6985381. So I think the expression with ToSingle() method > > is right... > > I think I have figured out out. > I changed the variables definition "result" and "result2" to Double and I delete > the "SX" in expression. And it is : > > int num = 3600; > Single XNT = 0.3F; > Double result = XNT * num ; > Double result2 = System.Convert.ToSingle(XNT * num); > > And, the value of two result is: > result -> 1080.00004291534 > result2 -> 1080 > > It seems that Single is more better than Double here... int num = 3600; Single XNT = 0.3F; Double result = XNT * num ; 1. num is converted into an 80-bit floating point. 2. XNT is converted into an 80-bit floating point. Since 0.3F cannot be represented precisely by a Single, the 80-bit floating point will similarly be imprecise. 3. (80-bit)XNT * (80-bit)num results in an imprecise answer due to the previous step. 4. The imprecise result in step 3 is stored into a Double. Since double shows more decimal point then Single, the imprecise part is shown. int num = 3600; Single XNT = 0.3F; Double result2 = System.Convert.ToSingle(XNT * num); Steps 1 to 3 are the same as previous. 1. num is converted into an 80-bit floating point. 2. XNT is converted into an 80-bit floating point. Since 0.3F cannot be represented precisely by a Single, the 80-bit floating point will similarly be imprecise. 3. (80-bit)XNT * (80-bit)num results in an imprecise answer due to the previous step. 4. The imprecise result in step 3 is converted into Single, truncating the imprecise part. 5. The truncated result from step 4 is converted into Double, and since 1080 can be stored precisely in a Single, converting it to Double gives a precise result. The conclusion will be that the 1st result appears imprecise due to the imprecise 0.3F to start with.
Show quote
Hide quote
> I believe this is a wrong conclusion. I think you spoke to the point. It is very helpful for me.> > int num = 3600; > Single XNT = 0.3F; > Double result = XNT * num ; > > 1. num is converted into an 80-bit floating point. > 2. XNT is converted into an 80-bit floating point. > Since 0.3F cannot be represented precisely by a Single, the 80-bit > floating point will similarly be imprecise. > 3. (80-bit)XNT * (80-bit)num results in an imprecise answer due to the > previous step. > 4. The imprecise result in step 3 is stored into a Double. Since > double shows more decimal point then Single, the imprecise part is > shown. > > > > int num = 3600; > Single XNT = 0.3F; > Double result2 = System.Convert.ToSingle(XNT * num); > > Steps 1 to 3 are the same as previous. > > 1. num is converted into an 80-bit floating point. > 2. XNT is converted into an 80-bit floating point. > Since 0.3F cannot be represented precisely by a Single, the 80-bit > floating point will similarly be imprecise. > 3. (80-bit)XNT * (80-bit)num results in an imprecise answer due to the > previous step. > 4. The imprecise result in step 3 is converted into Single, truncating > the imprecise part. > 5. The truncated result from step 4 is converted into Double, and > since 1080 can be stored precisely in a Single, converting it to > Double gives a precise result. > > The conclusion will be that the 1st result appears imprecise due to > the imprecise 0.3F to start with. Thank you! > The thing that's weird is that the calculation is being performed Besides forcing rounding as already noted elsewhere in this thread, there is > differently, independent of the precision (which must be the same in > either case), depending on context. I don't have time to look at it now, > and maybe by the time I do, someone else will have already figured it > out. But, one would expect that "XNT * num" would always produce the same > value, and that for a given value, dividing by "SX" would also always > produce the same value. another potential difference: Without the call to ToSingle, the calculation involves only variables which have verifiably constant values. So the compiler can perform constant propagation, performing the calculation at compile time. If the FPU setup registers (such as rounding mode) are set differently by the compiler, you could get very slightly different results. But I also don't agree with the OP when he said he got two different results. The values of the two expressions are as equal as floating-point numbers can get. Show quoteHide quote > __________ Information from ESET NOD32 Antivirus, version of virus signature database 4160 (20090616) __________> The only explanation for what you're seeing is that somewhere in there is > an incorrect assumption. To me, the most obvious suspect is the > Convert.ToSingle() method, but the documentation claims that > Convert.ToSingle(Single) always returns exactly the value that was passed > to it. > > And given all that, the most obviously explanation I see is that there's a > compiler bug that is either choosing the wrong overload for the ToSingle() > method (i.e. using ToSingle(Double), which could produce a subtle > difference in the result), or is actually generating different IL simply > because of the presence of the method call. There is a more remote > possibility that the ToSingle(Single) method does not in fact do what the > documentation says it does. > > In the meantime, you can look into those theories yourself if you like. > ILDASM.EXE can show you the IL generated in your program, where you can > look for specific differences in the code the compiler generates (i.e. > differences in the calculations, or using a different method overload than > one would expect given the code). To check to see what ToSingle(Single) > does, you'll either need to use Red Gate's Reflector (Google it) or > configure your IDE to download the .NET source while debugging, and then > step into the method. > > I'm curious myself, so if there's not an answer twelve hours or so from > now (when I'll actually have time to look at it myself), I'll see what I > can figure out. > > Finally, note that if it is a bug, it's possible it's been fixed since > .NET 2.0/VS 2005 (depending on whether it's a framework or compiler bug). > I'm only going to be able to test the code with .NET 3.5/VS 2008 at the > moment, so one thing you might want to do is try to test it yourself on a > more recent compiler and/or .NET version and see if it still happens. > That would be a very useful data point. > > Pete The message was checked by ESET NOD32 Antivirus. http://www.eset.com It happens that XjAcKs formulated :
Show quoteHide quote > Hi everyone. My source code is the following in VS2005: Want even more scary things? Try this:> > -------- > static void Main(string[] args) > { > int num = 3600; > Single XNT = 0.3F; > Single SX = 1546.08594F; > > Single result = (XNT * num) / SX; > Single result2 = System.Convert.ToSingle(XNT * num) / SX; > > System.Console.WriteLine(result); > System.Console.WriteLine(result2); > return; > } > -------- > > The result is "0.6985382", but the result2 is "0.6985381". > Why there are two diffrent result here? > > When "XNT * num", because "XNT" is the type of Single, I think the system > should automatic convert the result to Single. But when I manually add the > "System.Convert.ToSingle()", the diffrent result appeared. Any idea? > > Thank you! public class MyClass { static float f; static float Sum (float f1, float f2) { return f1+f2; } public static void Main() { f = Sum (0.1f, 0.2f); float g = Sum (0.1f, 0.2f); Console.WriteLine (f==g); // uncomment the next line and run again: //Console.WriteLine (f==g); // or use only this writeline: //Console.WriteLine (f==(float)g); Console.ReadKey(); } } Apparently the compiler can decide to keep float variables as regular stack variables or as register variables. Those latter ones exist only in the CPU and are stored in a different precision (80 bits as opposed to 64 if I remember correctly). And the 80 bit representation of some number will be different from the 64 bits version ... Hans Kesting
Show quote
Hide quote
> It happens that XjAcKs formulated : Thanks for you reply. I read your reply and understand your meaning. But, I >> Hi everyone. My source code is the following in VS2005: >> >> -------- >> static void Main(string[] args) >> { >> int num = 3600; >> Single XNT = 0.3F; >> Single SX = 1546.08594F; >> >> Single result = (XNT * num) / SX; >> Single result2 = System.Convert.ToSingle(XNT * num) / SX; >> >> System.Console.WriteLine(result); >> System.Console.WriteLine(result2); >> return; >> } >> -------- >> >> The result is "0.6985382", but the result2 is "0.6985381". >> Why there are two diffrent result here? >> >> When "XNT * num", because "XNT" is the type of Single, I think the >> system should automatic convert the result to Single. But when I >> manually add the >> "System.Convert.ToSingle()", the diffrent result appeared. Any idea? >> >> Thank you! > > Want even more scary things? Try this: > > public class MyClass > { > static float f; > > static float Sum (float f1, float f2) > { > return f1+f2; > } > > public static void Main() > { > f = Sum (0.1f, 0.2f); > float g = Sum (0.1f, 0.2f); > Console.WriteLine (f==g); > // uncomment the next line and run again: > //Console.WriteLine (f==g); > // or use only this writeline: > //Console.WriteLine (f==(float)g); > Console.ReadKey(); > } > } > > Apparently the compiler can decide to keep float variables as regular > stack variables or as register variables. Those latter ones exist only > in the CPU and are stored in a different precision (80 bits as opposed > to 64 if I remember correctly). And the 80 bit representation of some > number will be different from the 64 bits version ... > > Hans Kesting > > haven't know how it happend in my program yet. I think the variables in my program are all kept as regular stack variables because there are no "static" defined... XjAcKs XjAcKs wrote :
Show quoteHide quote >> It happens that XjAcKs formulated : It doesn't have to be a static variable. It's just that the compiler >>> Hi everyone. My source code is the following in VS2005: >>> >>> -------- >>> static void Main(string[] args) >>> { >>> int num = 3600; >>> Single XNT = 0.3F; >>> Single SX = 1546.08594F; >>> >>> Single result = (XNT * num) / SX; >>> Single result2 = System.Convert.ToSingle(XNT * num) / SX; >>> >>> System.Console.WriteLine(result); >>> System.Console.WriteLine(result2); >>> return; >>> } >>> -------- >>> >>> The result is "0.6985382", but the result2 is "0.6985381". >>> Why there are two diffrent result here? >>> >>> When "XNT * num", because "XNT" is the type of Single, I think the system >>> should automatic convert the result to Single. But when I manually add the >>> "System.Convert.ToSingle()", the diffrent result appeared. Any idea? >>> >>> Thank you! >> >> Want even more scary things? Try this: >> >> public class MyClass >> { >> static float f; >> >> static float Sum (float f1, float f2) >> { >> return f1+f2; >> } >> >> public static void Main() >> { >> f = Sum (0.1f, 0.2f); >> float g = Sum (0.1f, 0.2f); >> Console.WriteLine (f==g); >> // uncomment the next line and run again: >> //Console.WriteLine (f==g); >> // or use only this writeline: >> //Console.WriteLine (f==(float)g); >> Console.ReadKey(); >> } >> } >> >> Apparently the compiler can decide to keep float variables as regular stack >> variables or as register variables. Those latter ones exist only in the CPU >> and are stored in a different precision (80 bits as opposed to 64 if I >> remember correctly). And the 80 bit representation of some number will be >> different from the 64 bits version ... >> >> Hans Kesting >> >> > > Thanks for you reply. I read your reply and understand your meaning. But, I > haven't know how it happend in my program yet. I think the variables in my > program are all kept as regular stack variables because there are no "static" > defined... > > XjAcKs may decide to have some variables as 64 bit stack variables while others (the short-lived ones I presume) can be 80 bit register variables. But I don't understand the workings of the compiler enough to make an example without the static variable. Hans Kesting
Show quote
Hide quote
> XjAcKs wrote : OK, I will remember it. Thank you, Hans.>>> It happens that XjAcKs formulated : >>>> Hi everyone. My source code is the following in VS2005: >>>> >>>> -------- >>>> static void Main(string[] args) >>>> { >>>> int num = 3600; >>>> Single XNT = 0.3F; >>>> Single SX = 1546.08594F; >>>> >>>> Single result = (XNT * num) / SX; >>>> Single result2 = System.Convert.ToSingle(XNT * num) / SX; >>>> >>>> System.Console.WriteLine(result); >>>> System.Console.WriteLine(result2); >>>> return; >>>> } >>>> -------- >>>> >>>> The result is "0.6985382", but the result2 is "0.6985381". >>>> Why there are two diffrent result here? >>>> >>>> When "XNT * num", because "XNT" is the type of Single, I think the >>>> system should automatic convert the result to Single. But when I >>>> manually add the >>>> "System.Convert.ToSingle()", the diffrent result appeared. Any idea? >>>> >>>> Thank you! >>> >>> Want even more scary things? Try this: >>> >>> public class MyClass >>> { >>> static float f; >>> >>> static float Sum (float f1, float f2) >>> { >>> return f1+f2; >>> } >>> >>> public static void Main() >>> { >>> f = Sum (0.1f, 0.2f); >>> float g = Sum (0.1f, 0.2f); >>> Console.WriteLine (f==g); >>> // uncomment the next line and run again: >>> //Console.WriteLine (f==g); >>> // or use only this writeline: >>> //Console.WriteLine (f==(float)g); >>> Console.ReadKey(); >>> } >>> } >>> >>> Apparently the compiler can decide to keep float variables as regular >>> stack variables or as register variables. Those latter ones exist >>> only in the CPU and are stored in a different precision (80 bits as >>> opposed to 64 if I remember correctly). And the 80 bit representation >>> of some number will be different from the 64 bits version ... >>> >>> Hans Kesting >>> >>> >> >> Thanks for you reply. I read your reply and understand your meaning. >> But, I haven't know how it happend in my program yet. I think the >> variables in my program are all kept as regular stack variables >> because there are no "static" defined... >> >> XjAcKs > > It doesn't have to be a static variable. It's just that the compiler may > decide to have some variables as 64 bit stack variables while others > (the short-lived ones I presume) can be 80 bit register variables. > But I don't understand the workings of the compiler enough to make an > example without the static variable. > > Hans Kesting > > XjAcKs Hi XjAcKs,
The precision for Single (float) type is 7 digits (you are using more than that). If you change SX to 1546.086F, the program will behave correctly. If you need more precision, use double. Regards. XjAcKs wrote: Show quoteHide quote > Hi everyone. My source code is the following in VS2005: > > -------- > static void Main(string[] args) > { > int num = 3600; > Single XNT = 0.3F; > Single SX = 1546.08594F; > > Single result = (XNT * num) / SX; > Single result2 = System.Convert.ToSingle(XNT * num) / SX; > > System.Console.WriteLine(result); > System.Console.WriteLine(result2); > return; > } > -------- > > The result is "0.6985382", but the result2 is "0.6985381". > Why there are two diffrent result here? > > When "XNT * num", because "XNT" is the type of Single, I think the system should > automatic convert the result to Single. But when I manually add the > "System.Convert.ToSingle()", the diffrent result appeared. Any idea? > > Thank you! Hi kndg,
Thank you for you advise. But in my program, "1546.08594F" has some meaning and can't change it to 1546.086F. I think it is better to use Double instead of Snigle. Show quoteHide quote > Hi XjAcKs, > > The precision for Single (float) type is 7 digits (you are using more > than that). If you change SX to 1546.086F, the program will behave > correctly. > If you need more precision, use double. > > Regards. > > XjAcKs wrote: >> Hi everyone. My source code is the following in VS2005: >> >> -------- >> static void Main(string[] args) >> { >> int num = 3600; >> Single XNT = 0.3F; >> Single SX = 1546.08594F; >> >> Single result = (XNT * num) / SX; >> Single result2 = System.Convert.ToSingle(XNT * num) / SX; >> >> System.Console.WriteLine(result); >> System.Console.WriteLine(result2); >> return; >> } >> -------- >> >> The result is "0.6985382", but the result2 is "0.6985381". >> Why there are two diffrent result here? >> >> When "XNT * num", because "XNT" is the type of Single, I think the system should >> automatic convert the result to Single. But when I manually add the >> "System.Convert.ToSingle()", the diffrent result appeared. Any idea? >> >> Thank you! On Jun 10, 4:00 pm, XjAcKs <xja***@gmail.com> wrote:
Show quoteHide quote > Hi everyone. My source code is the following in VS2005: On Intel processors, Single is first converted into an 80-bit> > -------- > static void Main(string[] args) > { > int num = 3600; > Single XNT = 0.3F; > Single SX = 1546.08594F; > > Single result = (XNT * num) / SX; > Single result2 = System.Convert.ToSingle(XNT * num) / SX; > > System.Console.WriteLine(result); > System.Console.WriteLine(result2); > return; > } > -------- > > The result is "0.6985382", but the result2 is "0.6985381". > Why there are two diffrent result here? > > When "XNT * num", because "XNT" is the type of Single, I think the system should > automatic convert the result to Single. But when I manually add the > "System.Convert.ToSingle()", the diffrent result appeared. Any idea? > > Thank you! precision floating-point before calculation. The statement Single result = (XNT * num) / SX; would be doing an 80-bit XNT * 80-bit num / 80-bit SX, then converting it back to 32-bit Single. The statement Single result2 = System.Convert.ToSingle(XNT * num) / SX; would instead be 80-bit XNT * 80-bit num, then convert to Single Pass the 32-bit Single into System.Convert.ToSingle Then convert the result into 80-bit and divide by 80-bit SX, then converting back to Single. The 2nd case would have introduced more errors. BTW, you might consider using Double since Intel processors calculate Double directly (no conversion into 80-bit floating point), and so should run faster. Hi Li Huan,
Using SAME Intel machine, the expression (XNT * num) / SX will return 0.6985382 on .NET 0.6985381 on JAVA Can you explain this behaviour? Maybe someone who have Mono and/or Java on Linux machine can post their result here... Li Huan wrote: Show quoteHide quote > On Jun 10, 4:00 pm, XjAcKs <xja***@gmail.com> wrote: >> Hi everyone. My source code is the following in VS2005: >> >> -------- >> static void Main(string[] args) >> { >> int num = 3600; >> Single XNT = 0.3F; >> Single SX = 1546.08594F; >> >> Single result = (XNT * num) / SX; >> Single result2 = System.Convert.ToSingle(XNT * num) / SX; >> >> System.Console.WriteLine(result); >> System.Console.WriteLine(result2); >> return; >> } >> -------- >> >> The result is "0.6985382", but the result2 is "0.6985381". >> Why there are two diffrent result here? >> >> When "XNT * num", because "XNT" is the type of Single, I think the system should >> automatic convert the result to Single. But when I manually add the >> "System.Convert.ToSingle()", the diffrent result appeared. Any idea? >> >> Thank you! > > On Intel processors, Single is first converted into an 80-bit > precision floating-point before calculation. > > The statement > Single result = (XNT * num) / SX; > would be doing an 80-bit XNT * 80-bit num / 80-bit SX, then converting > it back to 32-bit Single. > > The statement > Single result2 = System.Convert.ToSingle(XNT * num) / SX; > would instead be > 80-bit XNT * 80-bit num, then convert to Single > Pass the 32-bit Single into System.Convert.ToSingle > Then convert the result into 80-bit and divide by 80-bit SX, then > converting back to Single. > > The 2nd case would have introduced more errors. > > BTW, you might consider using Double since Intel processors calculate > Double directly (no conversion into 80-bit floating point), and so > should run faster. On Wed, 10 Jun 2009 23:27:52 -0700, kndg <reply@this.newsgroup> wrote:
> Hi Li Huan, Note that the Java result is identical to the result you get if at each > > Using SAME Intel machine, the expression > > (XNT * num) / SX > > will return > 0.6985382 on .NET > 0.6985381 on JAVA > > Can you explain this behaviour? step of the calculation, the precision is 32-bit float (i.e. "Single" or "float"). Note also that Java, unlike .NET/C#, may sometimes execute code as interpreted. .NET will always JIT-compile your IL code to native before executing it. Since .NET is always executing the code as native, it has the luxury of being able to do things like promote the data type without introducing inconsistent results within the same execution session. If Java's JIT compiler were to promote the type, then the code could produce different results during the interpreted execution of the code than during the compiled execution of the code. Java _could_ address that by specifying the interpreter to do the same promotion, but then the promotion would have to happen on ALL platforms, and it's not necessarily the case that promoting to 64-bit float produces the same performance boost on all platforms. Such a requirement on the interpreter could interfere with the compiler's ability to general optimal code. The above is all speculation. It's entirely possible that the only reason there's a difference in Java is a completely arbitrary decision on the part of those who implemented .NET and those who implemented Java. Finally, you should keep in mind that this entire message thread is purely academic curiosity. If you have some program requirement that calculations produce exact results, then neither Single/float nor Double/double are appropriate. That's just not something those floating point types provide. Pete > Finally, you should keep in mind that this entire message thread is I am curious to know if I have a program requirement that calculations produce > purely academic curiosity. If you have some program requirement that > calculations produce exact results, then neither Single/float nor > Double/double are appropriate. That's just not something those floating > point types provide. > > Pete exact results, which should I use? On Thu, 11 Jun 2009 17:36:52 -0700, XjAcKs <xja***@gmail.com> wrote:
>> Finally, you should keep in mind that this entire message thread is It depends on the nature of those exact results.>> purely academic curiosity. If you have some program requirement that >> calculations produce exact results, then neither Single/float nor >> Double/double are appropriate. That's just not something those >> floating point types provide. >> Pete > > I am curious to know if I have a program requirement that calculations > produce exact results, which should I use? If you need floating point results that can always be represented as decimal, then the Decimal type will work. Note that even with Decimal, there are values that can't be represented exactly (e.g. 1/3). But for a lot of applications, it's fine. If you need to represent arbitrary fractions, then you'll have to create your own fractional type (or find an implementation someone else has already made). There's nothing built into .NET that does that. Note that one possibility is that you only _think_ you need exact results, and that in fact you really don't. You should consider that seriously before you complicate your life. :) Pete XjAcKs <xja***@gmail.com> wrote:
>> Finally, you should keep in mind that this entire message thread is None of the above. Floating point arithmetic NEVER produces exact results.>> purely academic curiosity. If you have some program requirement that >> calculations produce exact results, then neither Single/float nor >> Double/double are appropriate. That's just not something those floating >> point types provide. > >I am curious to know if I have a program requirement that calculations produce >exact results, which should I use? That's just the nature of floating point arithmetic. It's an approximation. You've already seen this. You wrote the number 1546.08594, but that number **CANNOT** be represented exactly as a floating point value. In binary, that number is an infinitely repeating fraction. It doesn't matter how many bits you use, the floating point representation will ALWAYS be an approximation. It's exactly the same as if I asked you to write down the EXACT decimal representation of 1/3. It can't be done. However, that's OK, because the number 1546.08594 is itself obviously an approximation. The KEY QUESTION you need to ask is, "how many digits/bits of precision do I have to begin with?" If that number was really measured to 9 digits of accuracy (which is highly doubtful), then you might need to consider doubles. They maintain about 15 digits. Further, every computation you do reduces the accuracy more and more. There are plenty of books and web sites that describe numerical analysis with floating point numbers. You just need to be aware. -- Tim Roberts, t***@probo.com Providenza & Boekelheide, Inc.
code access security
Weird behavior of ListView.ShowGroups property A Radius Search? Property and Global Variable Generic Interface syntax in VS 2005 using Old syntax No Implicit Conversion For Strongly Typed DataSet In VS2005 Merge XML Files from DataSets extending existing application Memory used in unmanaged space Greek letters with subscripts/superscripts |
|||||||||||||||||||||||