Click here to Skip to main content
15,893,663 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Math error width 'Decimal' type of variables or something else ?

Hello ,
I have made simple program for calculating square root of numbers
at 28 decimal places, that contains this function :

C#
decimal CalculateSquareRoot(decimal number)
{
   // declare variables
   decimal result;
   decimal square;
   decimal c;
   string end;		
			
   // calculate initial square root
   square = number * 0.5M;
			
   // determine add/sub coefficient
   c = FindC(square);
			
   result = square * square;
   end = ResultControl(result,number,c);
   while(end != "end")
   {
	while(end == "bigger" && c<=square)
	{
		square = square - c;    // !!! problematic line !!!
		result = square * square;
		end = ResultControl(result,number,c);
	}
	c = c / 10;
	while(end == "smaller")
	{
		square = square + c;
		result = square * square;
		end = ResultControl(result,number,c);
	}
	c = c / 10;
   }
   return square;
}


Algorithm is ok but I have found problem,
program do not calculate correct,
simple math operation such as subtraction

In the line 21 ( problematic line ) of program code :

square = square - c;

for values :

square = 11111111,061111080443055417550
c = 0,0000000000000000000001
square = 11111111,061111080443055417550 ? incorrect

This is incorrect, and as it can be seen it seems that
calculation is not done at all because the result of
calculation is the same as one of the addends.

This should be new value of 'square' variable afther subtraction operation
square = 11111111,0611110804430554175499

Since this calculation is inside the 'while' loop
program becomes unresponsive because of this error.

All variables are type of 'Decimal'
and this math operation should go without errors
since this type can accept numbers up to 28 decimals.

Also this same function works perfectly inside program where
variables are declared as type of 'BigInteger',
and that version of program can calculate square root of numbers
at wanted number of decimal places restricted only by quantity of memory.

I can't find pattern for this error and this example is not isolated case.

If someone had similar problem please answer how to solve it.

Program is written in IDE SharpDevelop ver 4.2.2, C#.

All the best,
Perić Željko
Posted
Updated 25-Dec-13 11:30am
v2

Precision of decimal number is 28-29 significant digits.

Number you are expecting as result of your calculation (11111111.0611110804430554175499) has 31 digits an cannot be correctly represented as decimal without truncation.

Following Sergey suggestion about BigInteger perhaps is a solution if you need to deal with very big precision. BigInteger dos not set limit for number of significant digits. But of course noting is free: arithmetic operations on BigInteger numbers are very slow.
 
Share this answer
 
Comments
Perić Željko 26-Dec-13 12:38pm    
Thanks for answer Adam, now I completely understand. I had overlooked the fact, in the definition of 'Decimal' type of number, that as result of any calculation it is going to be displayed maximum 28 digits including decimals, not float point number with 28 decimal places as I thought. Both proposed solutions constitute the answer. Thank You. All the best, Perić Željko
It looks like a perfectly accurate result for floating-point presentation of numbers. I hope you understand that there are real numbers, which are infinite objects by they natures, and their computer approximations, such as floating-point. You can learn more about it if you start here: http://en.wikipedia.org/wiki/Floating-point[^].

The types like BigInteger have a very different nature. It's pretty interested to see how they are implemented, which you can do, for example, if you download source code of Mono implementation and study it.

—SA
 
Share this answer
 
Comments
Perić Željko 25-Dec-13 18:22pm    
Thanks for answer but :
"Decimal is not a floating-point data type. The Decimal structure holds a binary integer value, together with a sign bit and an integer scaling factor that specifies what portion of the value is a decimal fraction. Because of this, Decimal numbers have a more precise representation in memory than floating-point types (Single and Double)."
Taken from MSDN
"Holds signed 128-bit (16-byte) values representing 96-bit (12-byte) integer numbers scaled by a variable power of 10. The scaling factor specifies the number of digits to the right of the decimal point; it ranges from 0 through 28. With a scale of 0 (no decimal places), the largest possible value is +/-79,228,162,514,264,337,593,543,950,335 (+/-7.9228162514264337593543950335E+28). With 28 decimal places, the largest value is +/-7.9228162514264337593543950335, and the smallest nonzero value is +/-0.0000000000000000000000000001 (+/-1E-28)."

So if I have understood correct when I subtruct such small value as
0,0000000000000000000001 (22 decimals or 1e-22)
from any decimal number there should be correct result and not like in this case incorrect,
since we can see all 28 decimal places when we show result, or precision and accuracy of calculation should not have anything to do with number presentation of numbers because in this case all numbers are within specified range.

All the best,
Perić Željko
Sergey Alexandrovich Kryukov 25-Dec-13 23:23pm    
I agree. Decimal type is quite different, but it has something in common with "real" floating-point types: limited precision. (Anyway, it's not possible to present infinite information contained in most of mathematical real numbers (do you realize that it is really infinite, even in one such number?) using finite-state machine, such as a computer.)
—SA
Adam Zgagacz 25-Dec-13 19:01pm    
SA comment/solution is valid. It doesn't really matter if it is float, double or decimal. All have limited number of significant digits. You cannot achieve very big precision with them.
Sergey Alexandrovich Kryukov 25-Dec-13 23:20pm    
Thank you very much, Adam. Just for clarification: I did not mean any specific type, I meant all floating-point types collectively.
—SA
Perić Željko 26-Dec-13 12:40pm    
Thank's for clarification, now I understand.All the best, Perić Željko

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900