X * y < z ?

Abstrakt:
Prüfe, ob dass Produkt zweier beliebigen Zahlen kleiner ist als eine
weitere Zahl - OHNE das Produkt zu berechnen

x * y <= z ?

Beispiel: RSA
P*Q soll kleiner als 2^64 sein.

Folgendes noch: Auf Overflow prüfen ist nicht erlaubt!

MfG
 
Also, warum man das Produkt nicht ausrechnen soll, versteh ich zwar nicht, aber so müsste es im Prinzip gehen:

Code:
If (X*Y) < Z then

Lg, D31~$0u1
 
Wie wäre es mit umformung?
x*y <= z
y <=z/x bzw. x<=z/y

//edit
bevor das unklar wird:
es müssen beide Bedingungen erfüllt sein damit x*y <= z wirklich stimmt
 
Zuletzt bearbeitet:
Für welchen Definitionsbereich ? Reelle Zahlen ?
Zunächst würde ich ich prüfen, ob eine der Zahlen größer ist als z (es sei denn es werden auch negative Zahlen zugelassen, dann müssen zusätzlich auch Vorzeichen geprüft werden). Sonst würde ich iwi "schummeln", dass man indirekt die Produkte erfährt. (=> Alles ohne Informatik bisher)
 
AlterHacker:
Beide müssen ja nicht zutreffen, denn wer sagt das x*y<z gilt?
das soll ja gerade rausgefunden werden.
und ob x,y positiv oder negativ sind ist bei der betrachtungsweise egal.
@Ownz:
Das müssen die reellen zahlen sein, denn die operationen < und > sind nicht auf komplexen Zahlen definiert,der Betrag aber schon,und das ist eine reelle Zahl.
@threadstarter:
wie Ownz schon sagte ein paar infos mehr wären super
 
Zuletzt bearbeitet:
stimmt hast recht.;)
Denkfehler meinerseits, da war ich wohl etwas zu "unfaul".
 
Steh ich dann jetzt auf dem Schlauch?

Wenn ich x*y <= z habe, kann ich durch x oder y dividieren. Dabei muss ich aber eine Fallunterscheidung machen. Wenn sich durch die Division das Vorzeichen nur einer Seite ändert, muss ich die Beziehung umdrehen. Ändern sich die Vorzeichen auf beiden Seiten, bleibt alles wie gehabt.

Man erhält also für

- x>0, y>0 und ein beliebiges z
- x<0 y<0 und ein beliebiges z
- x<0 y>0 und z>0
- x>0 y<0 und z>0

x <= z/y bzw. y<= z/x

- x<0 y>0 und z>0

x <= z/y bzw. y >= z/x

- x>0 y<0 und z<0

x >= z/y bzw. y <= z/x

Das zeigt aber doch, dass jeweils beide Bedingungen zutreffen müssen und zusätzlich die Grundannahmen im Bezug auf die Vorzeichen, oder irre ich?
 
@Ownz:
D = R^+

Die Umformung ist schonmal ein guter Ansatz:

x * y <= z = x > z/y

Setzt man Werte ein, so sieht man schön, dass es passt.

Hat jemand noch andere Vorschläge?

MfG
 
Hi Thunderbolt.
- x>0, y>0 und ein beliebiges z
-Nein für müsste dann gelten z>0 damit die oben genannten Bedingungen
müssten erfüllt werden
- x<0 y<0 und ein beliebiges z
-gleicher fall wie oben
- x<0 y>0 und z>0
- x>0 y<0 und z>0
-in beiden Fällen kann z <0 sein,und solange die oben genannte
Bedingungen erfüllt sind ist die vorraussetzung dann wahr.
-sollte z sogar echt kleiner 0 sein, so sieht man leicht ein, das
bei richtiger Umstellung das Vorzeichen wegdividiert wird.
Weswegen die Unterscheidung nach Vorzeichen hier nicht von
belangen ist

mfg

sw33t
 
Es gilt doch
log(xy)==log(x)+log(y)

Für negative Zahlen sollte eine Vorabgfrage und ggf. Normalisierung genügen (falls z negativ: x<0,y>0 oder y<0,x>0, falls z positiv: x,y<0 oder x,y>0). Technisch gesehen kann man darauf pfeifen - positiv oder negativ ist nur eine Sache der Interpretation der binären Darstellung *g*.

Btw:
Der "logarithmus" zur Basis 2 lässt sich trivial berechnen (bits zählen, Rest bilden - zuerst Anzahl der Bits (und damit die Potenzen) vergleichen und bei Bedarf noch die Reste). D.h man könnte auch ohne Logfunktion auskommen - alleine mit Potenzzerlegung und Addition.

Bsp zu der "Potenzzerlegung"
10*17<171
Zerlege in 2er Potenzen:

10=2^3 +2^1 (wie gesagt, einfaches Bitzählen/Bitabfragen zur Zerlegung genügt, man braucht keine Division oder Ähnliches)
17=2^4 +2^0
und
171=2^7 + 2^5+2^3+2^1+2^0

Ich schreibe mal weiter mit 2^, weil es die gewohnte Notation ist, allerdings sind die Basen gleich - daher reichen Exponenten schon für alle Operationen aus.

Die ganzen Multiplikationen werden bei Potenzen als Addition aufgefasst:
also "Kreuzmultiplikation" 17*10 = 2^4*2^3 + 2^4*2^1 + 2^1*2^0 + 2^3*2^0=
=2^(4+3)+2^(4+1)+2^(2+1)+2^(1+0) = 2^7+2^5+2^3+2^1
nun vergleiche die einzelnen Potenzstellen:
2^7+2^5+2^3+2^1 (+0*2^0)=170=10*17
||___||___||___| |
2^7+2^5+2^3+2^1+2^0 = 171
d.h 2^7=2^7 -> 7=7
2^5=2^5 -> 5=5 usw.

alle gleich, allerdings hat 171 noch 2^0 - das ist "mehr".
bei 170 wären
2^7+2^5+2^3+2^1 ==
2^7+2^5+2^3+2^1 (also gleich)
bei 10*17<169 hätte man
2^7+2^5+2^3+2^0=169
verglichen mit
2^7+2^5+2^3+2^1=170
=>falsch, da 2^1>1^0 -> 1>0

bei 192 =2^7+2^6 wäre man schon nach dem zweiten Vergelich fertig (da 2^6>2^5)

PS: es ist spät. kann sein, dass das Verfahren auch absoluter Humbug ist ;)
 
Das ist echt clever.
Kleiner Verbesserungsvorschlag:
erhöhe die Stelle an welcher die Potenz steht um 1,
dh:
2^0 wird zu 1
2^5 wird zu 6
so vermeidest du das bei 2^0 das additive neutrale Element einbezogen wird.
und da du die erhöhung auf beiden seiten machst,solltest du auch vergleichbare werte bekommen, Bsp:
(170)10 = (10101010)2
(171)10 = (10101011)2

wenn du das nun erhöhst steht dort,wenn man nur die exponenten betrachtet und addiert:
1+3+6+7 = 17 für 170, das gleiche gilt auch für 171(0+1+3+6+7),
da bei 2^0 die 0 addiert wird.

jetzt erhöhen wir mal das alles um 1:
2+4+7+8 = 21 für 170
1+2+4+7+8 = 22 für 171
voilá.

mfg

sw33t
 
2+4+7+8 = 21 für 170
1+2+4+7+8 = 22 für 171
voilá.
Meinst Du, dass man letzendlich nur die Summe der Exponenten vergleichen soll? Mein erster "intuitiver" Gedanke war nämlich wirklich die einzelnen Exponenten zu vergleichen. Denn die Summe ist imho nicht eindeutig.
Bsp:
2+4+6+8=20 für 170
2^1+2^2+2^5+2^8=294 bzw. Potenzerhöhung:
2+3+6+9=20 für 294

Oder habe ich das falsch verstanden?
 
Meinst Du, dass man letzendlich nur die Summe der Exponenten vergleichen soll? Mein erster "intuitiver" Gedanke war nämlich wirklich die einzelnen Exponenten zu vergleichen. Denn die Summe ist imho nicht eindeutig.
Bsp:
2+4+6+8=20 für 170
2^1+2^2+2^5+2^8=294 bzw. Potenzerhöhung:
2+3+6+9=20 für 294

Stimmt.X(
 
Hier mal ein PoC in Prolog:
Code:
bit_power(0,[]).
bit_power(Num,[2^Exp|Res]):- Exp is msb(Num),             %hier etwas gecheatet
                             NewNum is Num >< (1<<Exp),   %performanter Weg wäre
                             bit_power(NewNum,Res),!.     %aber aufwendiger umzusetzen

%zusammenfassen, da bei der "Multiplikation" auch
%[2^4, 2^2, 2^3, 2^1, 2^2, 2^0] als Ergebnis auftreten kann
trans([],[]).
trans([X],[X]).
trans([2^X,2^X|T],[2^Y|Res]):-Y is X+1,trans(T,Res),!.
trans([X,Y|T],[X|Res]):- X\=Y,trans([Y|T],Res),!.

transform(ExpList,Result):-msort(ExpList,Sorted),
                           trans(Sorted,Trans),
                           Sorted\=Trans,
                           transform(Trans,Result),!.
transform(Result,Result).
%'Kreuzaddition'
mul_exps(ExpList1,ExpList2,Res):-
        findall(2^ExpSum,(
                           member(2^Exp1,ExpList1),
                           member(2^Exp2,ExpList2),
                           ExpSum is Exp1+Exp2
                         ),Sums),
        transform(Sums,Trans),
        sort(Trans,Sorted),reverse(Sorted,Res).

cmp_pow([2^Exp1|_],[2^Exp2|_]):- Exp1<Exp2,!.             %ist ein Exponent kleiner =>fertig
cmp_pow([2^Exp1],[2^Exp2|T]):- T\=[],Exp1=:=Exp2,!.       %mehr Exponenten vorhanden =>eher größer
cmp_pow([2^Exp1|List1],[2^Exp2|List2]):- Exp1=:=Exp2,
                  cmp_pow(List1,List2),!.

compare(X*Y<Z):- bit_power(X,XBit),write(X=XBit),nl,
                 bit_power(Y,YBit),write(Y=YBit),nl,
                 bit_power(Z,ZBit),write(Z=ZBit),nl,
                 mul_exps(XBit,YBit,Mul),write(X*Y=Mul),nl,
                 cmp_pow(Mul,ZBit).
Zerlegt die Eingabe in 2-er Potenzen und
operiert damit. Eingabe in "natürlicher" Syntax: compare(X*Y<Z)

Code:
7 ?- compare(7*5<35).
7=[2^2, 2^1, 2^0]
5=[2^2, 2^0]
35=[2^5, 2^1, 2^0]
7*5=[2^5, 2^1, 2^0]
false.

8 ?- compare(7*5<36).
7=[2^2, 2^1, 2^0]
5=[2^2, 2^0]
36=[2^5, 2^2]
7*5=[2^5, 2^1, 2^0]
true.

9 ?- compare(71*35<36).
71=[2^6, 2^2, 2^1, 2^0]
35=[2^5, 2^1, 2^0]
36=[2^5, 2^2]
71*35=[2^11, 2^8, 2^7, 2^5, 2^4, 2^2, 2^0]
false.

10 ?- X is 71*35.
X = 2485.

11 ?- compare(71*35<2485).
71=[2^6, 2^2, 2^1, 2^0]
35=[2^5, 2^1, 2^0]
2485=[2^11, 2^8, 2^7, 2^5, 2^4, 2^2, 2^0]
71*35=[2^11, 2^8, 2^7, 2^5, 2^4, 2^2, 2^0]
false.

12 ?- compare(71*35<2486).
71=[2^6, 2^2, 2^1, 2^0]
35=[2^5, 2^1, 2^0]
2486=[2^11, 2^8, 2^7, 2^5, 2^4, 2^2, 2^1]
71*35=[2^11, 2^8, 2^7, 2^5, 2^4, 2^2, 2^0]
true.
 
Zurück
Oben