Answered by:
defects in type decimal and double
Question

hello everyone. here is a very important matter to be corrected as soon as possible. generally,type double can display an answer correct to more than 20 decimal places. yes,it works fine until here except for exponential system. whenever i try to find a decimal raised to the power of a proper fraction, i get a correct answer but only upto 13 decimal places. that is not fair at all! it is important to get as high precision as possible. consider this example:
input:2^(1/2)
output:1.4142135623731
this produces many errors when running a general purpose program requiring general calculations including "^".Just like this
input:2^(1/2)*2^(1/2)
output:2.0000000000001
but if 2^(1/2) is computed upto 20 decimal places,answer i get is precise! 2.
most important thing
i want that number of correct decimal places or approximation,which a windows 7 calculator has. i believe that this is someway easy to get rid of. please support.it is important for programs like calculator,worksheets,databases,etc. too!
Sunday, January 1, 2012 8:07 AM
Answers

hmmmmmm.................................
please consider that till now,i was having no problem with any data type related issues and even now but neglecting situations of complex exponents.
jeff supreme
Write your own power function. Extended precision types typically only have the basic operators add, subtract, multiply and divide. Intel based systems typically have 13 bit precision for doubles which all higher precision types use for power functions. Edited by JohnWein Sunday, January 1, 2012 3:30 PM
 Proposed as answer by Mike FengModerator Monday, January 2, 2012 12:29 PM
 Marked as answer by Mike FengModerator Friday, January 13, 2012 3:22 PM
Sunday, January 1, 2012 3:29 PM 
You may be forcing the calulation to use intermediate values that cannot retain the full precision of the original. For instance,
MsgBox(2 ^ (1 / 2) * 2 ^ (1 / 2).ToString)
does not demonstrate the problem you have described, whereas
MsgBox((2 ^ (1 / 2)) * (2 ^ (1 / 2)).ToString)
does. You need to ensure that intermediate values are maintained to at least the same precision as is required for the result. You should also ensure that all variables are explicitly declared as Double.Decimal values wll be converted to Double for exponentation, although I can't see how that would produce the error you describe. What is the actal code you used to demonstrate the problem with Decimals?
 Proposed as answer by Blackwood Sunday, January 1, 2012 2:24 PM
 Marked as answer by Mike FengModerator Tuesday, January 10, 2012 10:09 AM
 Unmarked as answer by Mike FengModerator Tuesday, January 10, 2012 10:09 AM
 Marked as answer by Mike FengModerator Friday, January 13, 2012 3:22 PM
Sunday, January 1, 2012 9:07 AM 
If you want to retain the most number of significant digits, use Decimal instead of Double.
http://msdn.microsoft.com/enus/library/5c53yzyb(v=vs.80).aspxThe exponentiation operator uses Doubles only. If you want to use the full precision of the Decimal type with exponentiation, you will need to write your own exponentiation operator.
http://msdn.microsoft.com/enus/library/zh100ckf(v=VS.80).aspxThe relationship between the Double or Decimal types and the String type is entirely controlled by the formatting information your provide when you do the conversion. If you do not provide any formatting information and allow the system to default (for instance "msgbox(e1)" ) then the results will likely not be what you want.
http://msdn.microsoft.com/enus/library/dwhawy9k.aspx Proposed as answer by Mike FengModerator Monday, January 2, 2012 12:29 PM
 Marked as answer by Mike FengModerator Friday, January 13, 2012 3:22 PM
Sunday, January 1, 2012 9:11 PM 
Since x^y = exp(y * ln(x))...
It may be possible to use other methods which converge more rapidly and/or are more accurate, but you can get quite close to the 2 you want:
Imports System.Decimal Module Module1 Const factorialDecSize As Integer = 27 ' Decimal only has sufficient size to hold (27!) Const factorialDblSize As Integer = 37 ' to be determined empirically Public factorialDec(factorialDecSize) As Decimal Public factorialDbl(factorialDblSize) As Double Private Sub SetUpFactorials() ' seed it with 0! = 1 factorialDec(0) = 1 For i = 1 To factorialDecSize factorialDec(i) = factorialDec(i  1) * i Next ' seed the first Double factorial using the last Decimal value factorialDbl(factorialDecSize) = factorialDec.Last For i = factorialDecSize + 1 To factorialDblSize factorialDbl(i) = factorialDbl(i  1) * i Next End Sub Function ln(x As Decimal) As Decimal ' from http://www.math.com/tables/expansion/log.htm Dim l As Decimal = Divide(Subtract(x, 1D), Add(x, 1D)) Dim divisor As Integer = 3 Dim lSquared As Decimal = Multiply(l, l) Dim z As Decimal = l Dim prevValue As Decimal Dim iterationCount As Integer = 0 Do z = Multiply(z, lSquared) prevValue = l l = Add(l, Divide(z, divisor)) divisor += 2 iterationCount += 1 Loop Until l.Equals(prevValue) ' OrElse iterationCount > someSaneValue Console.WriteLine("Iterations for ln({0}): {1}", x, iterationCount.ToString) Return Multiply(l, 2D) End Function Function exp(x As Decimal) As Decimal Dim r As Decimal = 1D Dim x0 As Decimal = x Dim prevValue As Decimal = Zero Dim iterationCount As Integer = 0 Dim i As Integer = 0 Do prevValue = r If i < factorialDecSize Then r = Add(r, Divide(x, factorialDec(i + 1))) Else ' try to squeeze a few more digits from it r = Add(r, CDec(x / factorialDbl(i + 1))) End If x = Multiply(x, x0) i += 1 iterationCount += 1 Loop Until r.Equals(prevValue) OrElse i = factorialDblSize Console.WriteLine("Iterations for exp({0}): {1}", x0, iterationCount.ToString) Return r End Function Function pow(x As Decimal, y As Decimal) As Decimal Return exp(Multiply(y, ln(x))) End Function Sub Main() SetUpFactorials() ' calculate 2^0.5 using Decimals Dim sqrt2 As Decimal = pow(2D, 0.5D) ' outputs 2.0000000000000000000000000000 Console.WriteLine(Multiply(sqrt2, sqrt2)) ' the traditional way of writing 2 Console.WriteLine("2") Console.ReadLine() End Sub End Module
(Remove the lines with iterationCount if desired.)
Andrew Marked as answer by Mike FengModerator Friday, January 13, 2012 3:22 PM
Monday, January 9, 2012 10:19 PM
All replies

You may be forcing the calulation to use intermediate values that cannot retain the full precision of the original. For instance,
MsgBox(2 ^ (1 / 2) * 2 ^ (1 / 2).ToString)
does not demonstrate the problem you have described, whereas
MsgBox((2 ^ (1 / 2)) * (2 ^ (1 / 2)).ToString)
does. You need to ensure that intermediate values are maintained to at least the same precision as is required for the result. You should also ensure that all variables are explicitly declared as Double.Decimal values wll be converted to Double for exponentation, although I can't see how that would produce the error you describe. What is the actal code you used to demonstrate the problem with Decimals?
 Proposed as answer by Blackwood Sunday, January 1, 2012 2:24 PM
 Marked as answer by Mike FengModerator Tuesday, January 10, 2012 10:09 AM
 Unmarked as answer by Mike FengModerator Tuesday, January 10, 2012 10:09 AM
 Marked as answer by Mike FengModerator Friday, January 13, 2012 3:22 PM
Sunday, January 1, 2012 9:07 AM 
The mathematics of number systems are pretty much cast in stone. This will help Computer number format representation of numbers in binary. This will help Data Type Summary (Visual Basic) with the representation of the number data types in Visual Basic.Sunday, January 1, 2012 11:53 AM

well, simplified:
 dim e1 as double=2^(1/2)
 msgbox(e1)
output is 1.4142135623731 being displayed in the message box. but according to data type assigned, it should be 1.4142135623730950489 or more precise.
it will be best if i get this output:1.4142135623730950488016887242097(as in windows 7 calculator).isn't there any way to do any one of these. please tell me if there is any strong link in between string and double.
jeff supremeSunday, January 1, 2012 12:24 PM 
hmmmmmm.................................
please consider that till now,i was having no problem with any data type related issues and even now but neglecting situations of complex exponents.
jeff supremeSunday, January 1, 2012 12:31 PM 
hmmmmmm.................................
please consider that till now,i was having no problem with any data type related issues and even now but neglecting situations of complex exponents. i would like to have the code of win 7 calculator.i love it.
jeff supreme
jeff supremeSunday, January 1, 2012 12:32 PM 
hmmmmmm.................................
please consider that till now,i was having no problem with any data type related issues and even now but neglecting situations of complex exponents.
jeff supreme
Write your own power function. Extended precision types typically only have the basic operators add, subtract, multiply and divide. Intel based systems typically have 13 bit precision for doubles which all higher precision types use for power functions. Edited by JohnWein Sunday, January 1, 2012 3:30 PM
 Proposed as answer by Mike FengModerator Monday, January 2, 2012 12:29 PM
 Marked as answer by Mike FengModerator Friday, January 13, 2012 3:22 PM
Sunday, January 1, 2012 3:29 PM 
If you want to retain the most number of significant digits, use Decimal instead of Double.
http://msdn.microsoft.com/enus/library/5c53yzyb(v=vs.80).aspxThe exponentiation operator uses Doubles only. If you want to use the full precision of the Decimal type with exponentiation, you will need to write your own exponentiation operator.
http://msdn.microsoft.com/enus/library/zh100ckf(v=VS.80).aspxThe relationship between the Double or Decimal types and the String type is entirely controlled by the formatting information your provide when you do the conversion. If you do not provide any formatting information and allow the system to default (for instance "msgbox(e1)" ) then the results will likely not be what you want.
http://msdn.microsoft.com/enus/library/dwhawy9k.aspx Proposed as answer by Mike FengModerator Monday, January 2, 2012 12:29 PM
 Marked as answer by Mike FengModerator Friday, January 13, 2012 3:22 PM
Sunday, January 1, 2012 9:11 PM 
oh my god! not bad idea. but i can only make it out for a decimal n raised to the power an integer, and not decimal. please help me to write the code if there is a way to get there.
jeff supremeSaturday, January 7, 2012 5:25 AM 
Calc.exe used to use IEEE 754 doubles for it's values, but microsoft completely rewrote it to use an arbitrary precision library.
Note the paper than Mr.Chen links to  it's very well known indeed, often listed in the top 10 papers that every programmer should read (which tells you how common misunderstandings about floating point numbers are!)
If you want to mimic Calculator then you will need to use a library, there isn't one in the standard .Net framework (though there is BigDecimal in the J# redistributable).
 Edited by jo0ls Saturday, January 7, 2012 12:09 PM
Saturday, January 7, 2012 12:09 PM 
oh my god! not bad idea. but i can only make it out for a decimal n raised to the power an integer, and not decimal. please help me to write the code if there is a way to get there.
Since x^y = exp(y * ln(x)), you can calculate it using the logarithm and exponential functions, which you can calculate using the Maclaurin series shown at List of Maclaurin series of some common functions, which can be calculated entirely using the Decimal data type (Decimal.Divide etc.). You just need to keep calculating terms until they're small enough to not affect the last decimal place of the result.

AndrewSaturday, January 7, 2012 2:57 PM 
You could start with a big number floating point library like this:
http://sine.codeplex.com/Pow with a floating point exponent is not there yet, but it does have all the required components for building the function with big numbers, either as part of the existing library (if you want to work in C) or as VB code within your application.
Sunday, January 8, 2012 12:26 AM 
Since x^y = exp(y * ln(x))...
It may be possible to use other methods which converge more rapidly and/or are more accurate, but you can get quite close to the 2 you want:
Imports System.Decimal Module Module1 Const factorialDecSize As Integer = 27 ' Decimal only has sufficient size to hold (27!) Const factorialDblSize As Integer = 37 ' to be determined empirically Public factorialDec(factorialDecSize) As Decimal Public factorialDbl(factorialDblSize) As Double Private Sub SetUpFactorials() ' seed it with 0! = 1 factorialDec(0) = 1 For i = 1 To factorialDecSize factorialDec(i) = factorialDec(i  1) * i Next ' seed the first Double factorial using the last Decimal value factorialDbl(factorialDecSize) = factorialDec.Last For i = factorialDecSize + 1 To factorialDblSize factorialDbl(i) = factorialDbl(i  1) * i Next End Sub Function ln(x As Decimal) As Decimal ' from http://www.math.com/tables/expansion/log.htm Dim l As Decimal = Divide(Subtract(x, 1D), Add(x, 1D)) Dim divisor As Integer = 3 Dim lSquared As Decimal = Multiply(l, l) Dim z As Decimal = l Dim prevValue As Decimal Dim iterationCount As Integer = 0 Do z = Multiply(z, lSquared) prevValue = l l = Add(l, Divide(z, divisor)) divisor += 2 iterationCount += 1 Loop Until l.Equals(prevValue) ' OrElse iterationCount > someSaneValue Console.WriteLine("Iterations for ln({0}): {1}", x, iterationCount.ToString) Return Multiply(l, 2D) End Function Function exp(x As Decimal) As Decimal Dim r As Decimal = 1D Dim x0 As Decimal = x Dim prevValue As Decimal = Zero Dim iterationCount As Integer = 0 Dim i As Integer = 0 Do prevValue = r If i < factorialDecSize Then r = Add(r, Divide(x, factorialDec(i + 1))) Else ' try to squeeze a few more digits from it r = Add(r, CDec(x / factorialDbl(i + 1))) End If x = Multiply(x, x0) i += 1 iterationCount += 1 Loop Until r.Equals(prevValue) OrElse i = factorialDblSize Console.WriteLine("Iterations for exp({0}): {1}", x0, iterationCount.ToString) Return r End Function Function pow(x As Decimal, y As Decimal) As Decimal Return exp(Multiply(y, ln(x))) End Function Sub Main() SetUpFactorials() ' calculate 2^0.5 using Decimals Dim sqrt2 As Decimal = pow(2D, 0.5D) ' outputs 2.0000000000000000000000000000 Console.WriteLine(Multiply(sqrt2, sqrt2)) ' the traditional way of writing 2 Console.WriteLine("2") Console.ReadLine() End Sub End Module
(Remove the lines with iterationCount if desired.)
Andrew Marked as answer by Mike FengModerator Friday, January 13, 2012 3:22 PM
Monday, January 9, 2012 10:19 PM