Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Westi on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Dealing with Large Numbers

Status
Not open for further replies.

Scott24x7

Programmer
Jul 12, 2001
2,828
JP
All,
I have some needs to capture and store some very large numbers (values over 100 and potentially over 1000 digits long). In my experiences with VFP, using the Numeric data type, after about 15 digits, it starts to do "funky stuff" with the significant digits, ie. dropping them and making them 0 value. I can't (don't want to) deal with scientific notation either, I need to be able to represent them as numeric values.
Does anyone have any experience in dealing with very large numbers in VFP? Are the libraries that exist that would allow me to extend VFPs numeric capability?
Thanks in advance for any help you can offer.



Best Regards,
Scott

"Everything should be made as simple as possible, and no simpler."[hammer]
 
I don't think any standard Visual C++/# or whatever is suited for that purpose.

You'll need a very specialized calculation routines especially written for this kind of precision if they even exist...

The handling in VFP should be string only for if you turn it into numbers the VFP (VC) precision takes over.


One possibility is though:

capture those big numbers into a memo field - which is the only possible solution for VFP doesn't accept fields larger than 254 or 255 characters long - and separate the whole number count from the decimal part of the big figures.

Then process the decimals as if they were whole numbers and of cource process the whole numbers too and after you've done that put the whole numbers and the decimal numbers together again to a string in a memo field.

This is a solution I would do and I think this could work.

Rob.
 
If you're going to try my suggested solution, when processing the decimal parts, be sure to use the same length on all decimal parts.
If you add numbers 150 chars long with numbers of 333 chars long you'll need to raise the 150 chars to 333 chars by adding 333-150 = 183 zero's to it otherwise you'll be having very strange results...

Rob.
 
Rob,
Fortunately, (well, I think it only slightly simplifies things) there are no decimal values. There are always whole numbers only.
I used to use Scheme from time to time for very large number manipulations, but that was years ago, and I've lost the plot in that language since then. (Lambda, lambda, lambda).
Partly why I'm wanting to use Fox, but the key is my need for storing the data results. The tricky part is, I can't figure out how to do what you are talking about in your suggestion... I have been puzzling this in my head for a very long time, and can't seem to create a working solution. I had already planned that Memo fields would be needed for values over 255 digits long. My initial testing will be with 100 digit values. If figure if I can make that work, taking it to any digit length shouldn't there after be a problem.
Fundamentally, I really only need the ability to Add, calculate the Square Root of and Divide functions. I don't need any other mathematic capability.
Thanks for the ideas so far...


Best Regards,
Scott

"Everything should be made as simple as possible, and no simpler."[hammer]
 
You'll need a very specialized calculation routines especially written for this kind of precision if they even exist.
Donald Knuth describes them in "The Art of Computer programming Vol 2". Unfortunately they're in a 30-year old Assembler<g>. Google "high precision arithmetic" brings up lots of references - all of which are beyond me.

Geoff Franklin
 
Are all the numbers positive?

Regards

Griff
Keep [Smile]ing
 
If so, here is an Add function for you:

Code:
FUNCTION ADDLONGSTRINGS
	PARAMETERS m.NUMBER1,m.NUMBER2
	PRIVATE m.NUMBER1,m.NUMBER2,m.CARRY,m.RESULT,m.TEMP1,m.TEMP2,M.SUMDIGIT
	M.NUMBER1 = ALLTRIM(m.NUMBER1)
	M.NUMBER2 = ALLTRIM(m.NUMBER2)

	** make the two strings the same length - to make processing simpler
	IF LEN(m.NUMBER1) > LEN(m.NUMBER2)
		M.NUMBER2 = RIGHT(SPACE(LEN(m.NUMBER1))+m.NUMBER2,LEN(m.NUMBER1))
	ELSE
		M.NUMBER1 = RIGHT(SPACE(LEN(m.NUMBER2))+m.NUMBER1,LEN(m.NUMBER2))
	ENDIF

	M.CARRY = 0
	M.RESULT = ""
	FOR I = LEN(m.NUMBER2) TO 0 STEP -1
		** extract the relevant digits
		M.TEMP1 = VAL(SUBSTR(m.NUMBER1,I,1))
		M.TEMP2 = VAL(SUBSTR(m.NUMBER2,I,1))
		** add them - with any previous carry
		M.SUMDIGIT = m.TEMP1 + m.TEMP2 + m.CARRY
		** see if they fall outside the scope (so the next carry can be assessed)
		IF m.SUMDIGIT > 9
			** calculate the carry
			M.CARRY = INT(m.SUMDIGIT/10)
			M.SUMDIGIT = m.SUMDIGIT - (m.CARRY * 10)
		ELSE
			** reset the carry if it's not relevant anymore
			M.CARRY = 0
		ENDIF
		** the the result on the left side of the existing result
		M.RESULT = STR(m.SUMDIGIT,1,0) + m.RESULT
		** get the next pair of digits
	NEXT
	M.RESULT = STR(m.CARRY,1,0) + m.RESULT
	** the result will now have leading zeros (result of adding spaces together)
	DO WHILE LEFT(m.RESULT,1) = "0"
		M.RESULT = RIGHT(m.RESULT,LEN(m.RESULT)-1)
	ENDDO
	RETURN(m.RESULT)

Regards

Griff
Keep [Smile]ing
 
I'm sure that could be tidied up (the carry test is actually redundant - but I think it makes it more readable) and you don't *really* need to process the two strings as if they are the same length (although it will take the same amount of time).

Adding control for signing would be easy enough too...


Good luck

Regards

Griff
Keep [Smile]ing
 
Griff,
They are all positive. So that makes it a little easier too. I'll play around with this, and then see how I can work out Square Roots...


Best Regards,
Scott

"Everything should be made as simple as possible, and no simpler."[hammer]
 
I *think* for square roots you're going to need a 'Log table' of some kind - that makes it easy(ish) once you've mastered longstring division/multiplication.

If all your numbers are really big integers the function I've provided will work.

Good luck

Regards

Griff
Keep [Smile]ing
 
Cool. I'll play around with it as soon as I can.


Best Regards,
Scott

"Everything should be made as simple as possible, and no simpler."[hammer]
 
If you can get addition and division working then you can use Newton's method for square roots. Iterate towards the square root of x by calculating:

Code:
delta = 1
NewEstimate = 0
OldEstimate = 1

DO WHILE delta >0.0000001
  NewEstimate = (x/OldEstimate + OldEstimate) /  2
  delta = ABS(NewEstimate - OldEstimate)
  OldEstimate = NewEstimate
  ? NewEstimate, delta
ENDDO

I don't know how slow this will be with 100-digit numbers but it might be faster than generating a 100-digit log table. The tradeoff depends how many of these calculations you want to do.

Geoff Franklin
 
tsh,
Thanks, will consider them as last ditch. Would really like to keep this is fox if at all possible. Speed is not the critical element here, as much as accuracy, and then ability to manipulate the data. Its fine that the values are not stored as "numerics".



Best Regards,
Scott

"Everything should be made as simple as possible, and no simpler."[hammer]
 
Hi Maniac, there are special Applications for Mathmatics, eg. Mathematica (
Or go to universalthread and try out "math unlimited" by Hilmar Zonneveld. That works with Arrays and already supports several mathematical functions including Sqrt().

By the way Geoff: Newtons iterative Method is fine for calulating the square root in few iterations with high precision. But each iteration is very expensive in processing time. There is an algorithm, that works with blocks of 2 digits and can calculate the sqrt in the needed precision in a single pass.

See here:
Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top