Floats sometimes get a bad rep. Actually, they scale very well, and should be well capable of representing any file size you encounter. The problem is, they cannot do this accurately, down to the very last digit. And if a result from a function is intended to be a Long, then simply converting it at that point to a Float isn't going ro fix the problem -- the significant part of the number has already been lost. Now there are several things that can be done to try to avoid this, and one of them is to use af ASM language at the junction where the procedure is called, so that the returned value can be dealt with in its component parts - assuming that the routine has all those component parts present in its registers.
If the language you are using does not return all the component parts, you may have to move a bit upstream, possibly using a WindoewAPI call in place of the built-in language support. For DOS compatability, Windows still supports the ability to call Interrupts, which likewise returns values in its registers. So ultimately, let's just say that you are going to end up with all the component parts of some very large number in two or more registers that somehow have to be combined into one large number.
At this point you could easily decide that a Float is not the way to go. True, it should scale sufficiently for the job, but you probably do not want to lose the accuracy of your byte count. As structure involving two Longs could also work, but the math gets a bit trickyy, what with carries and everything. You want a painless way to do this, and you really find you are not happy with the fact that the language isn't giving you much help at this point.
One solution has been the adoption of string arithmetic. That is, any number can be represented in string form, such as "1234567890123", and made virtually any size. Depending upon the length of an individual string, the number of digits allowed could be hundreds, thousands, or even more digits in length. The limit in PureBASIC is a maximum of 250 characters in a string. Strings can also be used to represent a decimal part by allowing a decimal point {",") somewhere in the string. but often this is not supported, as it makes the resulting computations somewhat more difficult to perform.
Now imagine if you had two numbers in string form to add together, such as "1234567890123456" plus "45678901234", How would you perform
this? Going back to the way you learned to add in school, you would
approach it somthing like this:
Code: Select all
"1234567890123456"
+ "45678901234"
In other words, you would approach it with the two values aligned from the right., And then you add, digit-by-digit, from right to left, remembering if you have a carry for the next position or not/ Now when adding two numbers, digit by digit, the worse case senerio is adding teo "9"'s for the first add. The result is "18", which is "8" plus a carry of "1". On the second and subsequent adds, the worse case is adding two "9".s with a carry of "1". This combination would give you a "19", which would be a "9" with a carry of "1". In other words, if there is a carry, it will always be a "1", nothing more, unless you are adding a column of numbers together.
To make the job simpler. it would help if the length of both strings was the same. You can accomplish this easily by adding a string of leading "0"'s to the shorter string like so"
Code: Select all
Numb1$= "1234567890123456"
Numb2$= "0000045678901234"
And you could use a FOR - NEXT loop to range through the whole sequence
Code: Select all
carry=0
ans$=""
For a=Len(numb1$) To 1Step -1
digit1=Val(Mid(numb1$,a,1))
digit2=Val(Mid(numb2$,a,1))
digit3=digit1+digit2+carry
ans$=Str(digit3 Mod 10)+ans$
carry=Int(digit3/10)
Next
If carry
Ans$="1"+ans$
EndIf
But wait! Can;t we use the fact that the computer can process multiple digits at the same time as a way to make this faster? Of course we can!
For instance, suppose we want to process the results in terms of six digits at a time. We just have to make sure that the length of both digit strings is a multiple of six
Code: Select all
a=Len(numb1$)
b=Len(numb2$)
If a<b
a=b ;pick the longer string to start with
EndIf
b=(a*6+5)/6 ;force a roundup if over a multiple of 6
If b>Len(numb1$)
numb1$=String(b-Len(numb1$),"0")+numb1$
EndIf
If b>Len(numb2$)
numb2$=String(b-Len(numb2$),"0")+numb2$
EndIf
carry=0
ans$=""
For a=b-5 to 1 Step -6
digits1=Val(Mid(numb1$,a,6)
digits2=Val(Mid(numb2$,a,6)
digits3=digits1+digits2+carry
tmpans$=Str(digits3)
ans$=right(tmpans$,6)+ans$
carry=Len(tmpans$)=7
Next
If carry
ans$="1"+ans$
EndIf
Now back to the heading of this message: You can find a number of libraries on the internet that support string arithmetic operations. These generally go by the name of BIG INT or something similar. Some claim to support string calculations of up to 2 GBytes, and include not only additiion and subtrtaction, but multiply, divide, logs, trigs, and other processes. Obviously the more advanced libraries are handling decimal points and extended decimal places just fine. But the bad thing about string arithmetic is that it is not very efficient. Each character, encoded into 8 bits, has only ten states reflected: The ASCII codes for digits "0" through "9". If you subdivided each byte into 4 bits (sometimes called a nyble),
you would still have 16 possible states, of which the first ten could represent the values 0 through 9 (from 0000 to 1011). This is called
Binary Coded DEcimal, or BCD for short. That means a string of 250 characters could represent as many as 500 digits!. Of course there would
have to be some added conversion time, and the ANS$ string could not just simply be printed to the console as-is, but it would mean more efficient packing of the values.
But if you are going that far, you could also consider that each byte on its own could represent 256 values, from 0 to 255. That compares to just the 100 possible states those same bits would represent in BCD, or just ten states in ASCII form. In bimary form then, 250 characters would represent 250^256 states (you work it out, I don't have anything on hand that will handle numbers that large)..
So either the code above should help you get started with some version of string arithmetic, or you can now go looking for a library on the internet that has all the routines you could ever want or use.
