Overløb!

Tags:    delphi

Jeg er ved at lave et program, som kan kryptere. I den forbindelse skal jeg gange to tal, men jeg opdaget at hvis tallenes produkt (Tal1 * Tal2) overstiger overløbsgrænserne for tal-typen melder Delphi ikke fejl, men synes at vælge et nyt tal mere eller mindre tilfældigt. Nu har jeg imidlertid fundet en løsning på at gange de to tal ved at finde primtal og så derefter finde modulo. Problemet er blot at det er tidskrævende at finde primtal osv. Derfor vil jeg gerne at man på en eller anden måde kan teste om udregningen giver overløb. Er der nogen, som har en løsning på dette problem (og ja, jeg har prøvet med Int64).

Jacob Christiansen

Yeah Baby, Yeah!



5 svar postet i denne tråd vises herunder
1 indlæg har modtaget i alt 3 karma
Sorter efter stemmer Sorter efter dato
Jeg er ved at lave et program, som kan kryptere. I den forbindelse skal jeg gange to tal, men jeg opdaget at hvis tallenes produkt (Tal1 * Tal2) overstiger overløbsgrænserne for tal-typen melder Delphi ikke fejl, men synes at vælge et nyt tal mere eller mindre tilfældigt. Nu har jeg imidlertid fundet en løsning på at gange de to tal ved at finde primtal og så derefter finde modulo. Problemet er blot at det er tidskrævende at finde primtal osv. Derfor vil jeg gerne at man på en eller anden måde kan teste om udregningen giver overløb. Er der nogen, som har en løsning på dette problem (og ja, jeg har prøvet med Int64).


Du kan slå Overflow checking til under Project -> Project Options -> Compiler. Så kaster Delphi en exception som du kan fange med try finally i stedet for bare at lave overløb og "starte forfra" (altså forsætte regnestykket fra den laveste integer-værdi).

Yeah Baby, Yeah!

Jeg forstår hvor du vil hen, men det er ikke meningen, at brugeren skal konfronteres med en fejlmeddelse eller programmet stopper. Hvis der er overløb skal programmet behandle data på en anden og meget mere tidskrævende metode. Derfor er det vigtigt, at jeg kan teste om de to tals produkt er korrekt eller ej. Har du et kode eksempel du kan give mig?


Brug Try except omkring din tildeling, så skulle du gerne fange den exception som Delphi smider.
Dog skal du nok tænke dig lidt om hvis det er i et loop hvor du skal fange exceptionen, da Try Except sænker hastigheden drastisk.

Her er en bid af dok'en fra Delphi omkring overflow:

"Enabling overflow checking slows down your program and makes it somewhat larger, so use {$Q+} only for debugging."


Jeg har lavet en lille Delphi/Asm funktion som ganger 2 tal sammen og returnere resultatet + om der har været overflow:

function MulCheck(AVal1, AVal2 : Cardinal; var Overflow : Boolean) : Cardinal; stdcall;
asm
pushf // remember flag values.
mov byte ptr [ecx], 0 // Overflow := False;
mul eax,edx // Result := (AVal1 * AVal2);
jno @no_overflow // if HasOverflowed then
mov byte ptr [ecx], 1 // Overflow := True;
@no_overflow: // Exit;
popf // restore flags to old values
end;

Du kan lave tilsvarende functioner til + og -. Alt hvad der skal til er at ændre "mul eax,edx" til "add eax, edx" eller "sub eax, edx".

Håber det hjælper.

Michael.






Hvad med extended så ?



Jeg er ved at lave et program, som kan kryptere. I den forbindelse skal jeg gange to tal, men jeg opdaget at hvis tallenes produkt (Tal1 * Tal2) overstiger overløbsgrænserne for tal-typen melder Delphi ikke fejl, men synes at vælge et nyt tal mere eller mindre tilfældigt. Nu har jeg imidlertid fundet en løsning på at gange de to tal ved at finde primtal og så derefter finde modulo. Problemet er blot at det er tidskrævende at finde primtal osv. Derfor vil jeg gerne at man på en eller anden måde kan teste om udregningen giver overløb. Er der nogen, som har en løsning på dette problem (og ja, jeg har prøvet med Int64).


Du kan slå Overflow checking til under Project -> Project Options -> Compiler. Så kaster Delphi en exception som du kan fange med try finally i stedet for bare at lave overløb og "starte forfra" (altså forsætte regnestykket fra den laveste integer-værdi).




Jeg er ved at lave et program, som kan kryptere. I den forbindelse skal jeg gange to tal, men jeg opdaget at hvis tallenes produkt (Tal1 * Tal2) overstiger overløbsgrænserne for tal-typen melder Delphi ikke fejl, men synes at vælge et nyt tal mere eller mindre tilfældigt. Nu har jeg imidlertid fundet en løsning på at gange de to tal ved at finde primtal og så derefter finde modulo. Problemet er blot at det er tidskrævende at finde primtal osv. Derfor vil jeg gerne at man på en eller anden måde kan teste om udregningen giver overløb. Er der nogen, som har en løsning på dette problem (og ja, jeg har prøvet med Int64).


Du kan slå Overflow checking til under Project -> Project Options -> Compiler. Så kaster Delphi en exception som du kan fange med try finally i stedet for bare at lave overløb og "starte forfra" (altså forsætte regnestykket fra den laveste integer-værdi).

Yeah Baby, Yeah!

Jeg forstår hvor du vil hen, men det er ikke meningen, at brugeren skal konfronteres med en fejlmeddelse eller programmet stopper. Hvis der er overløb skal programmet behandle data på en anden og meget mere tidskrævende metode. Derfor er det vigtigt, at jeg kan teste om de to tals produkt er korrekt eller ej. Har du et kode eksempel du kan give mig?




function MulCheck(AVal1, AVal2 : Cardinal; var Overflow : Boolean) : Cardinal; stdcall;
asm
pushf // remember flag values.
mov byte ptr [ecx], 0 // Overflow := False;
mul eax,edx // Result := (AVal1 * AVal2);
jno @no_overflow // if HasOverflowed then
mov byte ptr [ecx], 1 // Overflow := True;
@no_overflow: // Exit;
popf // restore flags to old values
end;


Ups!

MEGET VIGTIGT:
Fjern "stdcall;" fra funktionen (ellers virker det ikke da Delphi så bruger en anden calling convention. Det vil sige at med StdCall så bliver params push'et på stacken og uden bliver de overført via registerne).

Det var alt :0)[Redigeret d. 13/03-03 15:13:51 af Michael Skovslund]



t