How can I convert an array of DWORDs that create a very large number into a BYTE array? I'm learning about ADC and and would like to print my numbers.
i would use uhex$, and perhaps left$ and right$ macros, depending on what i wanted
in this example, each byte is seperated by a space character
you may want to add cr/lf's as needed
mov eax,SomeDWord
call SplitDW
.
.
.
SplitDW PROC
push eax
print right$(uhex$(eax),2),32 ;byte 0
mov eax,[esp]
print left$(right$(uhex$(eax),4),2),32 ;byte 1
mov eax,[esp]
print right$(left$(uhex$(eax),4),2),32 ;byte 2
pop eax
print left$(uhex$(eax),2),32 ;byte 3
ret
SplitDW ENDP
I have the following really big number code (256 bit number):
reallyBigNumber DWORD 1, 0, 0, 0, 0, 0, 0, 0
This should result in just the number '1'. But if I had it this way:
reallyBigNumber DWORD 0, 0, 0, 0, 0, 0, 0, 1
That's a number that I can't even begin to print. Is there a function available that will allow me to pass in the pointer to my number and my size of DWORDs and maybe load a BYTE buffer with the result?
You could simply dump byte by byte of your bignum as dedndave suggested. But you want to print the decimal representation of bignum, right?
This proc would do it, but you'll have to modify it (because it has msb FIRST, whereas in your bignum MSB is LAST). So you have to reverse the logic of the loop, and then you've got to adjust the parameter names
Bin2Dec proc uses ebx ecx edx edi
LOCAL Ten: DWORD
LOCAL Testz:DWORD
mov Ten, 10
mov edi, OFFSET g_szDecNum ; a buffer for the decimal representation of bignum
ALIGN 4
OuterLoop:
xor edx, edx
mov ecx, LENGTHOF g_dwArray ; g_dwArray = your bignum, length in BYTES
mov ebx, OFFSET g_dwArray ; address of bignum
mov Testz, 0
ALIGN 4
InnerLoop:
mov eax, [ebx]
div Ten
mov [ebx], eax
test eax, eax
jz IL1
mov Testz,1
ALIGN 4
IL1:
add ebx, 4
loop InnerLoop
mov al,dl
add al,"0"
stosb
test Testz,1
jnz OuterLoop
mov al,0
stosb
invoke szLen,ADDR g_szDecNum
.if eax > 1
lea eax,g_szDecNum
mov eax,rev$(eax)
.endif
ret
Bin2Dec endp
HTH, cobold
CAUTION: bignum is destroyed after conversion. You might want to save it before!
QuotereallyBigNumber DWORD 0, 0, 0, 0, 0, 0, 0, 1
that IS a really big number - lol
i thought you just wanted to view the bytes
to make a big decimal string, Cobold's proc looks about right
but, it is good to understand conversion principles, as opposed to taking some proc and copy/paste it into your program
basically, we want to convert a value from base 2 to base 10 - that is the hard part
then, we want to convert the base 10 digits to ASCII characters - that is the easy part
in base 2, each bit is a "digit" - base 10 digits may be expressed as base 2 values, 0000 to 1001
when we use the DIV instruction, we are using a base 2 dividend and divisor to get a base 2 quotient and remainder
quotient + remainder/divisor = dividend/divisor (all base 2 values)
it is important to note that the remainder value alone is somewhat meaningless
we need to know what the divisor is in order to evaluate it, as it represents only a portion of the fractional expression
one way to convert between bases is to use logarithms:
log
m(x) = log
n(x) / log
n(m)
the problem here is that the value you have given as an example is a 225-bit integer (with potential to be 256-bits)
we have no mechanism to load that large of an integer into the FPU if we wanted to get the log
the method Cobold gives is a simple alternative
it is a multiple-precision division loop
we continually divide the value by 10 and use the remainder as a decimal digit
each time we divide, we add a new digit to the decimal string
the first division provides us with the last digit in the result
the last division provides the first digit (highest order)
as we store each decimal digit, we add 30h to it to make it an ASCII character (30h = ASCII "0")
when there is nothing left to divide, we are done
as you can see, there is no way to divide such a large number all at once
even if we could, it may cause an overflow error because the quotient is also too large for a 32-bit register
for example, we can divide a 64-bit number by a 32-bit number
but, if the 64-bit dividend is large and the 32-bit divisor is small (like 10), it can
cause overflow because the resulting quotient must also fit into a 32-bit register
the largest value we can divide by 10 without overflow is 0FFFFFFFFh x 10d + 9, or 42,949,672,959 (36-bits long)
in order to handle larger dividends, we can cascade DIV instructions together, each one performing "partial division"
the inner loop of Cobold's code cascades DIV instructions together to perform this type of multiple-precision division
if we unrolled his inner loop and designed it make a single pass for 256-bit dividends, it might look like this:
DividendA dd 0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh
DivisorA dd 10h
QuotientA dd 8 dup(?)
RemainderA dd ?
mov ecx,DivisorA
xor edx,edx
mov eax,DividendA+28
div ecx
mov QuotientA+28,eax
mov eax,DividendA+24
div ecx
mov QuotientA+24,eax
mov eax,DividendA+20
div ecx
mov QuotientA+20,eax
mov eax,DividendA+16
div ecx
mov QuotientA+16,eax
mov eax,DividendA+12
div ecx
mov QuotientA+12,eax
mov eax,DividendA+8
div ecx
mov QuotientA+8,eax
mov eax,DividendA+4
div ecx
mov QuotientA+4,eax
mov eax,DividendA
div ecx
mov QuotientA,eax
mov RemainderA,edx
the final remainder (RemainderA) is a value from 0 to 9 - a single decimal digit
we would add the ASCII "0" to that remainder and store it as our first digit
in Cobold's code, the new QuotientA value overwrites the old DividendA value on each pass
that way, with each successive pass, we are dividing a value ~1/10th the size of the previous pass
when all the bits in the dividend are 0, there is no more number left to divide, so you know you are done
one way to make Cobold's code faster would be to divide by 100 instead of 10
that way, there are half as many passes in the outer loop
we get 2 decimal digits on each pass - the remainder is now a binary value from 0 to 99
we can use the AAM instruction to split it into 2 decimal digits, then convert and store both at once
aam ;split into 2 digits
or ax,3030h ;make them ASCII
xchg al,ah ;swap the order
then, we store the word from AX into the string instead of a byte from AL
you may have to supress a single leading 0 in the string
ded,
I didn't know that you know so much about number systems. Just want to tell you that I appreciate your post, and that it motivated me to enhance the Bin2Dec proc.
Have a nice day.
rgds
cobol(d) - because I used to code a lot in COBOL - yes I'm not a youngster anymore
that AAM trick will make it almost twice as fast - gl :U
btw - there are a bunch of guys in here that know more than i do - lol
and, there are much faster methods to do this
i like this method because it is small and simple and, once you have it debugged, you can depend on the correct result
some of the other methods are questionable, in that regard
and it is impractical to test all possible values
speed isn't usually all that critical with big-nums
it's not like we have to convert 100,000 of these values every day
usually, we only want to convert a few values, and then, only need to do it a few times
cobold: Thanks for your response. I'll work with that and see what I can come up with. I think I saw a post some time ago about you working on the Euler project puzzles. I'm hoping to get my LARGE number skills up enough to some some of those bad boys. I'm in the learning stage right now of how large numbers can be created and how to convert/express them as strings. Maybe I'm backwards in my thinking of MSB and LSB .. shoot, do I have my array backwards?
dedndave: I'm going to need to print your post and take it with me to lunch today.
With all of the algor speed gurus I thought there might already be something like this created. Add, sub, mul, div .. and so forth. Then a series of functions to convert to and from bytes. If not then ... this is going to be more fun that I thought.
Thanks for the help.
there are a few guys in here working on their own big-num lib's
Bruce is one (bruce1948)
Steve is another one of them i think (FORTRANS)
http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic
near the bottom of that wiki page is a table of bignum libraries
just above that is another table with some calculators and fractals
Hi Dave,
Yeah, I'm trying to get a consistant set of fixed point
routines put together. But it's slow going. I have various
pieces lying around, but now a mish-mash. You can search
the assembly news groups for stuff as well. Here is one such.
Richard Pavlicek
Below is a fast, compact routine that will write any number in ASCII
decimal up to 64,536 decimal digits! Hope that's enough. :)
;--- WRITE NUMBER IN ASCII DECIMAL
;--- Call with:
;--- ds:si = pointer to HIGH dword of number
;--- cx = size of number in double words
;--- es:di = END pointer for result string (if di = 0, result is
;--- stored from 0FFFFh downward, allowing maximum 64K digits)
;--- Returns:
;--- es:di = pointer to START of ASCII digit string
;--- cx = number of digits (0 = 64K)
WDECP:
push di ;save to find ASCII digit count later
WDEC1:
push cx ;save dword count
push si ;save high pointer
sub di,8 ;make space for 8 decimal digits
mov ebx,100000000 ;100 million
sub edx,edx ;initialize remainder
WDEC2:
mov eax,[si] ;get dword of dividend
div ebx ;divide by 100 million
mov [si],eax ;save quotient
sub si,4 ;move to next dword (if any)
loop WDEC2 ;repeat
mov eax,edx ;remainder (0-99999999)
sub edx,edx ;extend for division
mov ebx,10000 ;divisor to make 4-digit groups
div ebx ;dx = 0-9999, ax = 0-9999
mov bl,100 ;divisor to make 2-digit groups
div bl ;ah = 0-99, al = 0-99
push ax ;preserve al
mov al,ah ;least significant 2 digits
aam ;ah = 0-9, al = 0-9
xchg al,ah ;reverse order
shl eax,16 ;hold in upper half of eax
pop ax ;restore most significant digits
aam ;ah = 0-9, al = 0-9
xchg al,ah ;reverse order
or eax,30303030h ;make ASCII
mov es:[di],eax ;most significant 4 digits
mov ax,dx ;least significant (0-9999)
div bl ;ah = 0-99, al = 0-99
push ax ;preserve al
mov al,ah ;least significant 2 digits
aam ;ah = 0-9, al = 0-9
xchg al,ah ;reverse order
shl eax,16 ;hold in upper half of eax
pop ax ;restore most significant digits
aam ;ah = 0-9, al = 0-9
xchg al,ah ;reverse order
or eax,30303030h ;make ASCII
mov es:[di+4],eax ;least significant 4 digits
pop si ;restore high dword pointer
pop cx ;restore dword count
cmp dword ptr[si],0 ;is high dword zeroed yet?
jne WDEC1 ;no, continue with same count
sub si,4 ;yes, move to next dword (if any)
loop WDEC1 ;reduce count and continue if more
mov al,'0' ;check for leading zeros to cleanup
mov cx,8 ;maximum needed to check
repe scasb ;advances di PAST first non-zero digit
dec di ;point to first non-zero digit in string
pop cx ;restore original pointer (was di)
sub cx,di ;difference = number of ASCII digits
retn
Cheers,
Steve N.
Thanks!
good plan - i see he divides by 100000000, then by 10000, then by 100 and uses AAM - to get 8 at a time - lol
i should try 4 at a time with my 64-bit routine - 20 decimal digits max - perfect - 5 passes
thing is - my 64-bit code currently has no memory accesses at all - not even push/pop - all in registers
EDIT - that routine is for 16-bit protected mode programs, Steve ?
it needs a little re-work
Hi Dave,
I would think 16-bit real mode. Though, come to think of
it, 16-bit protected mode would be the same except for calls
and returns? I never used it as-is, just as one of about six to
eight routines to write my own one time. It was one of the
more interesting ones though.
Regards,
Steve N.
well - he is using ds:si and es:di, but also using 32-bit registers
the only way i know of mixing them together is 16-bit protected mode - lol
it wouldn't be difficult to make a 32-bit proc out of it
Hi Dave,
You can use 32-bit instructions and registers in 16-bit real
mode. I have done so a number of times. Weird looking but
useful.
Quote
it wouldn't be difficult to make a 32-bit proc out of it
Have at it. Should be easy (which was one of the reasons
I posted it). But then it would probably try to print more
than 64,536 decimal digits.
Cheers!
Steve N.
Mines only unsigned integer I have addition, subtraction, multiplication and division working and i can print them. This is only at a low level though needs a layer above before it really becomes usable, this is because i've taken an easy option and the routines expect all numbers to be the same length, keeps the routines a little bit shorter and maybe faster.
Bruce
LOL. You say that is should be easy to convert but I'm having a heck of a time. From Dave's comments it sounds like this is well optomized so I'm trying to convert and learn at the same time ... that might be my problem but I'm not totally sure what it's doing.
ok - i have converted the routine to work with win32
i managed to get a couple speed-ups along the way
there are still a few things i want to change:
1) make it an "invoke" routine, rather than calling and returning parameters in register
2) preserve ebx, ebp, esi, edi for use with win32
3) this version overwrites the input value - i can make the first pass put it on the stack, preserving the original
if you give me a little time, i will post the completed proc and a file
in the mean time, you can test it for me and see if i injected any bugs - lol
see post below - attachment:
http://www.masm32.com/board/index.php?action=dlattach;topic=12186.0;id=6633
This looks so different from mine. I'm just guessing with my conversion so I'm going to focus on your version. I have so much to learn.
let's hope i got it right - lol
i noticed something - in the previous post, the end of string pointer points to end of string +1
i will fix the previous post in case someone tries to run that code
for this one, the original value is retained, as well as ebx, ebp, esi, edi:
INVOKE Arbitrary2Str,
lpFirstDword,
dwNumberOfDwords,
lpResultStringEnd
lpFirstDword = offset of input value
dwNumberOfDwords = number of dwords in input value
lpResultStringEnd = offset of end of result string + 1 (null terminator)
Returns: eax = pointer to first byte of ASCII decimal string
ecx = number of decimal digits
output for a 1024 bit value (all 1's)
17976931348623159077293051907890247336179769789423065727343008115773267580550096
31327084773224075360211201138798713933576587897688144166224928474306394741243777
67893424865485276302219601246094119453082952085005768838150682342462881473913110
540827237163350510684586298239947245938479716304835356329624224137215
length = 309
see the attached file
EDIT - revision 3
EDIT - revision 4
updated attachment...
http://www.masm32.com/board/index.php?action=dlattach;topic=12186.0;id=6633
i made one last change (and cleaned up the comments)
instead of pointing to the last dword, the input parameter points to the first dword of the input value
a bit more convenient to use
Hi,
Looking at the code (Dave's and Richard's), I thought
there was something fishy going on. Well, not what I was
looking at. But, I have a suggestion to improve the routine(s).
Change
mov cx,8 ;maximum needed to check
repe scasb ;advances di PAST first non-zero digit
To
pop cx ;restore original pointer (was di)
push cx
repe scasb ;advances di PAST first non-zero digit
For smaller numbers with a LOT of leading zeroes. Tested
with the original routine, not Dave's improved version.
The original post.
http://groups.google.com/group/comp.lang.asm.x86/browse_thread/thread/2296450bda0c5398?hl=en#
Regards,
Steve N.
hiya Steve
you only need to examine 8 leading 0's
the way the loop is written, it won't create any more than that
i am sure there are many ways to improve this routine
Lingo, Drizz, and Jochen could have a ball with it - lol
i am no expert at optimizing code - i just wanted it to work
i have tried several values and it seems to be ok
i made a modified version of the routine that gives me the number of loop passes and leading zero's
89884656743115795386465259539451236680898848947115328636715040578866337902750481
56635423866120376801056005693993569667882939488440720831124642371531973706218888
39467124327426381511098006230470597265414760425028844190753411712314407369565552
70413618581675255342293149119973622969239858152417678164812112068607
Length: 308
Loop Passes: 39
Leading Zeros: 4
Press any key to continue ...
4294967295
Length: 10
Loop Passes: 2
Leading Zeros: 6
Press any key to continue ...
updated attachment...
http://www.masm32.com/board/index.php?action=dlattach;topic=12186.0;id=6633
i see that i need to make a 4th revision - lol
if you invoke it with size=0, it hangs
let me fix that.....
ok - revision 4
0
Length: 1
Loop Passes: 0
Leading Zeros: 0
Press any key to continue ...
this attachment has revision 4 and a test program
note: the test version of the routine has additional code in it that is not required for normal use
i plan to make one FINAL version of this thing - then go play with something else - lol
i need to check the input length to make sure it isn't too large
as such, i will want to return the status in EAX, as is standard practice in win32
that means the output string pointer will get moved to EDX
revision 5 coming up....
(if my electricity stays on - lol)
i need some input from you guys, here
if the input size is 0, i can return a 0 string easily enough, which seems to be mathematically correct
should i return an error condition in that case ?
it's possible that in real execution you will have the opportunities to create a 0 and will need to have the 0 returned. creating room for a really large number does not gaurantee that the situation will return a really large number. with that, i guess if it's determined that the big number is really just loaded with a DWORD then a different algor would be run. if the bignum is 0 then it would be a non-error and the buffer returns a <"0", 0>. i'm working from an iPhone so it's hard to test right now. i do think you are awesome for working so diligently on this. wow!
i dunno 'bout "diligent" - lol
i just want a proc that is usable
on the LAST (lol) revision that i am working on, i am adding tests for errors
i am also changing it to point to the beginning of the output buffer (you have to specify the length)
while i am at it - lol - i decided to add support for selecting signed or unsigned input values
that way, i don't have to have a revision 6 - lol
Quote from: dedndave on August 29, 2009, 03:55:11 PM
i need some input from you guys, here
if the input size is 0, i can return a 0 string easily enough, which seems to be mathematically correct
should i return an error condition in that case ?
Hi Dave,
Actually a case can be made for null not being equal to
zero. And the empty set is not the same as the set of
zero. For erroneous input I vote for flagging an error and
doing as little else as possible. If the input is bad, what
says the output buffer is okay? However, it's your call.
Either way, document it so the result is defined.
Regards,
Steve N.
Thanks for your input, Steve
i was trying to accomodate an off-the-wall case where they may be using variable-length values
something like "it takes N number of bits to express M set of values"
after giving it more thought, i think you are right
for unsigned integers, if Q is the number of possible values and N is the number of bits
Q = 2N
No of Bits Formula Number of Possible Values
1 21 2
2 22 4
3 23 8
4 24 16
but i think that is only a valid equation for N > 0 - if we DID plug a 0 in for N, Q = 1
of course, in most cases, they will have a constant there (the same constant throughout the entire program)
all in all, i think you are right - a 0 length is more likely to be caused by a coding error than by intention
i feel i should return some kind of a valid string pointer in all cases
(if they try to print a string at address 0, it crashes with access violation, as an example)
Quote from: dedndave on August 30, 2009, 02:24:39 PM
but i think that is only a valid equation for N > 0 - if we DID plug a 0 in for N, Q = 1
Right, which is the number of states possible with no choices.
One of those nice, valid answers that doesn't have much use.
Quote
i feel i should return some kind of a valid string pointer in all cases
(if they try to print a string at address 0, it crashes with access violation, as an example)
But aren't they passing to you the pointer to the string
buffer? If they send you a zero, what are you going to do
with it?
?,
Steve N.
QuoteIf they send you a zero, what are you going to do with it?
hmmmm.....
my first "impulse thought" would be to return a pointer to a 0-byte in the .text or .rdata segment - lol
i suppose the right thing to do is to pass them back their 0 and let them crash - lol
garbage in - garbage out, right ?
i don't want to add a bunch of overhead to the routine that is going to slow it down
i just want to do "the right thing", whatever that is
i am just now noticing that windows list of error descriptions sux rox - lol
they do not have these messages, which i would think seem rather natural choices:
1) The requested operation would cause stack overflow.
2) The requested operation would cause output buffer overflow.
(no wonder windows is full of security issues - they don't even have a decent code set aside for simple buffer overflow)
on the other hand, they have 458 different error codes that all generate the same description:
"Waiting for a process to open the other end of the pipe." (error codes 536-993)
at least they got that one covered - lol
the idiot that made the list was probably out in the back alley smoking crack with
the guy from intel that decided they didn't need LAHF/SAHF on 64-bit processors
EDIT - here's another example:
error 122 - "The data area passed to a system call is too small."
why didn't they just say, "The output buffer is too small."
because they used the word "system", we can't use it for non-API functions ?
and another:
error 87 - "The parameter is incorrect." (very helpful - lol)
why not take some of the "pipe" error codes i mentioned above and say:
"Paramater 1 is invalid"
"Paramater 2 is invalid"
"Paramater 3 is invalid"
"Paramater 4 is invalid"
"Paramater 5 is invalid"
"Paramater 6 is invalid"
"Paramater 7 is invalid"
"Paramater 8 is invalid"
there isn't one for "The input value is too large.", either - lol
Hi,
Quotegarbage in - garbage out, right ?
Right. I really don't think you have much choice.
As with:
Quotethe idiot that made the list was probably out in the back alley smoking crack with
the guy from intel that decided they didn't need LAHF/SAHF on 64-bit processors
Just when you think you've made it idiot-proof, they
come up with a more persistant idiot. The example with
LOOP being too fast for Micro$oft's installer, so instead of
fixing the installer, break the LOOP instruction comes to mind.
Ah well, Some times the best thing to do really is do nothing.
Best regards,
Steve N.
i am half-tempted to return pointers to my own predefined error strings
it's simple, it probably takes less space than the code to do otherwise, and it helps the guy debug his code
HI,
I have my fixed point routines working, more or less, more checking
for errors is needed. Anyway, I can have hundreds of digits on either
side of the decimal point. If I was going to do it over, I think I would
just do floating point routines.
Currently implemented (Unsigned):
Addition,
Subtraction,
Division using shifts and subtracts,
Multiplication using shifts and adds,
Multiplication using multiply and accumulate,
Display fixed point number as decimal,
Convert ASCII to fixed point number,
and Copy.
I can't see any real use for this type of math package. A floating
point package with extended precision might be useful. But the
80-bit FPU has got to cover most problems nicely. If I don't just
forget about it, the next steps would be, a compare routine, a
shell to handle signed arithmetic, and possibly, a square root.
Anyway,
Steve N.
ok - hopefully this is the last revision for the unsigned routine
i had thought about combining signed and unsigned into one routine
but, i considered there is no reason the unsigned routine should suffer speed loss (small diff)
so, i changed the plan to creating one routine for unsigned values and one for signed values
this is the unsigned version - i am working on the signed version
there are a couple ways to do it, so i have to write it both ways and compare performance
i may combine them into one routine, still - see how it goes
anyways, here is unsigned - revision 5 - with a test program
Tested on my 1.6 atom and everything was quick except for the last ... but that's a really big number!! And I hope you don't mind me disecting what you did to understand better .. and ask questions.
Hi,
Looks good, congrats.
Regards,
Steve N.
thanks guys
yes - that IS a big number - lol - 128 Kb+ result string
i found a minor mistake on my part
i test to see if, when the input size is converted to bytes, it overflows (cf)
if it does, i flag it as a "input too large error" - it should be "invalid input length"....
dec edi ;point to last dword
shl edi,2 ;in bytes
jc A2Str7 ;error - input length too large
should be....
dec edi ;point to last dword
shl edi,2 ;in bytes
jc A2Str6 ;error - input length invalid
i dunno what i was thinking - lol
it won't affect normal operation - i will update when i finish the signed version
ok guys - i need your input again
the best way to handle negative values (signed, of course) is to convert them to positive values first
it takes less time to do that than it would to extract decimal digits from a signed value, which would also slow down positive values
the overhead is not that signifigant, as the code is executed once prior to the ascii conversion loop
so - the question i have is this:
would it be better to have one routine that handles signed and unsigned formats (requiring an additional parameter)
or to have two seperate routines, one for signed, one for unsigned
seeing as how there are only a few people interested in this thread (lol), we will have a small vote-count
EDIT - nevermind guys - lol
the best solution: write all three routines and let the guy pick his own poison
I had the occasion during the past week to play myself with bignums because of a math problem published on one of those sites which I follow. The first part involved raising numbers to some power, dividing them by a number under 1000, and then multiplying them together. The final step was to convert the resulting binary number (almost 1100 bytes) to decimal and add up the digits to provide the required answer. I guess my eventual algo was proper because the submitted answer was accepted as correct.
If anyone is interested to try it, here's the description of that problem.
Quote3!=6
The divisors of 6 are : 1, 2 , 3 and 6
The sum of the divisors of 6 is 1+2+3+6=12.
The sum of the digits of 12 is 3.
It can be calculated that the sum of the divisors of 10! is 15334088.
The sum of the digits of 15334088 is 32.
Find the sum of the digits of the sum of the divisors of 1000!
As a side note, my algo ran in less than 3 ms.
that's cool Ray - lol
you saw the length the routine posted above could handle ?
i am trying to get ling long kai fang going - it can handle even longer ones
just haven't had much time to spend on it
as for 3 ms ? we don't understand "ms" - we need clock cycles - lol
Hutch ... is that a ProjectEuler puzzle or some other site?
that's Raymond - not Hutch - lol
and i think that is the site he likes to tackle - i have seen him mention it in other posts
Ray is our resident FPU expert - his site has a few nice libraries and a great "plain-English" FPU tutorial
the tutorial is also part of the masm32 package (\masm32\tutorial\fputute)
Ray's site:
http://www.ray.masmcode.com/
Quoteis that a ProjectEuler puzzle or some other site
It was published on another "minor league" site where problem difficulty is generally at the low end of the scale. This one came out of the blue and was actually proposed by one of the gugus at PE. It may be easy coding for those using HLL languages having access to some bignum library.
The only real difficulty is to know how to compute a sum of divisors without actually identifying all those divisors. For example, using your calculator, you can determine that 1000! is equal to approx. 4*10
2567. But that big number would then have almost 3*10
106 distinct divisors! :eek
Ray ... can you tell us what the site is? I have solved 10 PE and working on more. PE's submissions seem to be locked so even though I have solutions I can't seem to post my answers. Also, I have yet to find a forum where I can discuss what I did and get feedback. If you know of a place let me know.
QuoteI can't seem to post my answers
Do you mean you can't enter your result and find out if it correct or not,
or do you mean you can't post your code on the forum after your solution is accepted as correct???
If it is the latter, those fora were designed primarily for educational purposes. Most of the posts are definitely not educational as far as I'm concerned. Most simply post their source code without any explanation, often in a language which is not understandable. In order to keep the data base within reasonable limits, it was decided that once the number of posts to a problem exceeds 100, such forum would be locked on the belief that no significant addition to the knowledge base could be anticipated.
I can remember one member contacting me to re-open one forum because he thought his algo running in less than 200 ms was a major advancement. I replied that, if he would be sufficiently tenacious and study carefully the available posts, he could come up with an algo running in less than 5 ms (less than 1 ms in assembly). I even wrote a PDF on the subject. He has not made any other such request.
As for the other "minor leagur" site, you can find it at:
http://www.cstutoringcenter.com/problems/
Although that site also has a forum, it is NOT for posting nor discussing source code. If you are coding in assembly, we could certainly exchange info for some of the problems (solved by both of us) on a personal basis.
my eyes are blue
the bear is white
Thomas
i have created a new thread for a newer version...
http://www.masm32.com/board/index.php?topic=12363.new#new