Delphi Even Odd Problems - delphi

Having a problem whenever i want when typing in 2 4 6 8 10 etc i want to have the answer to come out as Even but cant seem to to find the solutioin
if (Edit1.Text = '2' ) then
Edit2.Text := 'Even'
else
Edit2.Text := 'Odd'
Tryed to divide 2 but it always fails.

Convert the text to an integer and use the Odd function:
if Odd(StrToInt(Text)) then
// the value is odd

You need to first convert the text in the textbox to a numeric type like Integer, and then compare that value by modulus of 2 (the remainder of integer division):
var
value: Integer;
begin
...
value := StrToInt(Edit1.Text);
if ((value mod 2) = 0) then
Edit2.Text := 'Even'
else
Edit2.Text := 'Odd';
...
end;
There is nice and short explanation on mod operator here:
FreePascal Wiki on Mod:
mod (modulus) divides two numbers and returns only the remainder that
is a whole number. For instance, the expression a:= 13 mod 4; would
evaluate to 1 (a=1), while b := 12 mod 4; would evaluate to 0 (b=0).

Related

Program keeps telling that number I wrote isn't integer

I made a program and it constantly tells me that the number I input isn't an integer.
I'm entering 100010110101 and it pops up with this error:
code:
procedure TForm1.Button1Click(Sender: TObject);
var
m,lo,cshl,cdhl,cjhl,csl,cdl,cjl:integer;
begin
m := StrToInt(Edit1.Text);
cshl := m div 100000000000;
cdhl := m div 10000000000 mod 10;
cjhl := m div 10000000000 mod 100;
csl := m div 1000000000 mod 1000;
cdl := m div 100000000 mod 10000;
cjl := m div 10000000 mod 100000;
lo := cjl + cdl * 10 + csl * 100 + cjhl * 1000 + cdhl * 10000 + cshl *100000;
ShowMessage(IntToStr(lo));
end;
Consider how Delphi (and most languages) handle 32-bit integers: Wikipedia
In this context, Integer is a 32-bit integer, and any value less than -2,147,483,648 or greater than 2,147,483,647 IS NOT a valid 32-bit integer.
The "common sense" would indicate, that integers range from -∞ to +∞, but that is not the case in computer architecture.
Use Int64 if you want to "cover" more values.
In your case, the code should look like this:
var
m,lo,cshl,cdhl,cjhl,csl,cdl,cjl:Int64;
begin
m := StrToInt64(Edit1.Text);
...
end;
Cheers

Delphi - Random Combination (Math)

I have a BIG problem here and do not even know how to start...
In short explanation, I need to know if a number is in a set of results from a random combination...
Let me explain better: I created a random "number" with 3 integer chars from 1 to 8, like this:
procedure TForm1.btn1Click(Sender: TObject);
var
cTmp: Char;
sTmp: String[3];
begin
sTmp := '';
While (Length(sTmp) < 3) Do
Begin
Randomize;
cTmp := IntToStr(Random(7) + 1)[1];
If (Pos(cTmp, sTmp) = 0) Then
sTmp := sTmp + cTmp;
end;
edt1.Text := sTmp;
end;
Now I need to know is some other random number, let's say "324" (example), is in the set of results of that random combination.
Please, someone can help? A link to get the equations to solve this problem will be enough...
Ok, let me try to add some useful information:
Please, first check this link https://en.wikipedia.org/wiki/Combination
Once I get some number typed by user, in an editbox, I need to check if it is in the set of this random combination: S = (1..8) and k = 3
Tricky, hum?
Here is what I got. Maybe it be usefull for someone in the future. Thank you for all people that tried to help!
Function IsNumOnSet(const Min, Max, Num: Integer): Boolean;
var
X, Y, Z: Integer;
Begin
Result := False;
For X := Min to Max Do
For Y := Min to Max Do
For Z := Min to Max Do
If (X <> Y) and (X <> Z) and (Y <> Z) Then
If (X * 100 + Y * 10 + Z = Num) Then
Begin
Result := True;
Exit;
end;
end;
You want to test whether something is a combination. To do this you need to verify that the putative combination satisfies the following conditions:
Each element is in the range 1..N and
No element appears more than once.
So, implement it like this.
Declare an array of counts, say array [1..N] of Integer. If N varies at runtime you will need a dynamic array.
Initialise all members of the array to zero.
Loop through each element of the putative combination. Check that the element is in the range 1..N. And increment the count for that element.
If any element has a count greater than 1 then this is not a valid combination.
Now you can simplify by replacing the array of integers with an array of booleans but that should be self evident.
You have your generator. Once your value is built, do something like
function isValidCode( Digits : Array of Char; Value : String ) : Boolean;
var
nI : Integer;
begin
for nI := 0 to High(Digits) do
begin
result := Pos(Digits[nI], Value ) > 0;
if not result then break;
end;
end;
Call like this...
isValidCode(["3","2","4"], RandomValue);
Note : it works only because you have unique digits, the digit 3 is only once in you final number. For something more generic, you'll have to tweak this function. (testing "3","3","2" would return true but it would be false !)
UPDATED :
I dislike the nested loop ^^. Here is a function that return the nTh digit of an integer. It will return -1 if the digits do not exists. :
function TForm1.getDigits(value : integer; ndigits : Integer ) : Integer;
var
base : Integer;
begin
base := Round(IntPower( 10, ndigits-1 ));
result := Trunc( value / BASE ) mod 10;
end;
nDigits is the digits number from right to left starting at 1. It will return the value of the digit.
GetDigits( 234, 1) returns 4
GetDigits( 234, 2) returns 3
GetDigits( 234, 3) returns 2.
GetDigits( 234, 4) returns 0.
Now this last function checks if a value is a good combination, specifying the maxdigits you're looking for :
function isValidCombination( value : integer; MinVal, MaxVal : Integer; MaxDigits : Integer ) : Boolean;
var
Buff : Array[0..9] of Integer;
nI, digit: Integer;
begin
ZeroMemory( #Buff, 10*4);
// Store the count of digits for
for nI := 1 to MaxDigits do
begin
digit := getDigits(value, nI);
Buff[digit] := Buff[digit] + 1;
end;
// Check if the value is more than the number of digits.
if Value >= Round(IntPower( 10, MaxDigits )) then
begin
result := False;
exit;
end;
// Check if the value has less than MaxDigits.
if Value < Round(IntPower( 10, MaxDigits-1 )) then
begin
result := False;
exit;
end;
result := true;
for nI := 0 to 9 do
begin
// Exit if more than One occurence of digit.
result := Buff[nI] < 2 ;
if not result then break;
// Check if digit is present and valid.
result := (Buff[nI] = 0) or InRange( nI, MinVal, MaxVal );
if not result then break;
end;
end;
Question does not seem too vague to me,
Maybe a bit poorly stated.
From what I understand you want to check if a string is in a set of randomly generated characters.
Here is how that would work fastest, keep a sorted array of all letters and how many times you have each letter.
Subtract each letter from the target string
If any value in the sorted int array goes under 0 then that means the string can not be made from those characters.
I made it just work with case insensitive strings but it can easily be made to work with any string by making the alphabet array 255 characters long and not starting from A.
This will not allow you to use characters twice like the other example
so 'boom' is not in 'b' 'o' 'm'
Hope this helps you.
function TForm1.isWordInArray(word: string; arr: array of Char):Boolean;
var
alphabetCount: array[0..25] of Integer;
i, baseval, position : Integer;
s: String;
c: Char;
begin
for i := 0 to 25 do alphabetCount[i] := 0; // init alphabet
s := UpperCase(word); // make string uppercase
baseval := Ord('A'); // count A as the 0th letter
for i := 0 to Length(arr)-1 do begin // disect array and build alhabet
c := UpCase(arr[i]); // get current letter
inc(alphabetCount[(Ord(c)-baseval)]); // add 1 to the letter count for that letter
end;
for i := 1 to Length(s) do begin // disect string
c := s[i]; // get current letter
position := (Ord(c)-baseval);
if(alphabetCount[position]>0) then // if there is still latters of that kind left
dec(alphabetCount[position]) // delete 1 to the letter count for that letter
else begin // letternot there!, exit with a negative result
Result := False;
Exit;
end;
end;
Result := True; // all tests where passed, the string is in the array
end;
implemented like so:
if isWordInArray('Delphi',['d','l','e','P','i','h']) then Caption := 'Yup' else Caption := 'Nope'; //yup
if isWordInArray('boom',['b','o','m']) then Caption := 'Yup' else Caption := 'Nope'; //nope, a char can only be used once
Delphi rocks!
begin
Randomize; //only need to execute this once.
sTmp := '';
While (Length(sTmp) < 3) Do
Begin
cTmp := IntToStr(Random(7) + 1)[1]; // RANDOM(7) produces # from 0..6
// so result will be '1'..'7', not '8'
// Alternative: clmp := chr(48 + random(8));
If (Pos(cTmp, sTmp) = 0) Then
sTmp := sTmp + cTmp;
IF SLMP = '324' THEN
DOSOMETHING; // don't know what you actually want to do
// Perhaps SET SLMP=''; to make sure '324'
// isn't generated?
end;
edt1.Text := sTmp;
end;

How do I omit the leading 0 from a 128C bar code?

If I put 12345, for example, in a "text" bar code's property, the output is 012345.
This "0" is the problem. How I can remove this?
I'm using Delphi 2010 and FastReport 4.9.72.
A Code 128C barcode needs to be an even number of digits. This is by design.
There is a 1:1 mapping between the numbers and the resulting output, and the output is 2-digit aligned. In the case of 1 the Code 128C representation of this number is 01
if the value was 12 then the underlying representation would be 12
so the digits 628 can only be represented by 0628
The wikipedia article about Code 128 explains the differences between the 128A, 128B and 128C encodings.
To remove leading zeros from a string:
function RemoveLeadingZeros(const S: String): String;
var
I, NumZeros: Integer;
begin
Len := 0;
for I := 1 to Length(S) do
begin
if S[I] <> '0' then Break;
Inc(NumZeros);
end;
if NumZeros > 0 then
Result := Copy(S, NumZeros+1, MaxInt)
else
Result := S:
end;

Validating an input in Pascal (pre release material)

I'm playing around with the comp 1 pre release material, but I can't seem to asnwer this properly in Pascal compiling in delphi...
This question refers to the function RollBowlDie.
This function has no validation of the input value.
What you have to do....
Make a copy of the Skeleton Program. Add additional statements to the function RollBowlDie so that it ensures that the input BowlDieResult is in the range 1 to 6 before allowing the game to continue and outputs an error message if not.
Add further statements to the function RollBowlDie so that it also checks that the input
BowlDieResult does not cause the program to crash if it is the wrong data type and instead outputs an error message when this is detected.
Test the amended function to show that it does not allow inputs that are out of range.
Test the amended function to show that it does not crash if an incorrect data type is added.
This is the RollBowlDie function.
Function RollBowlDie(VirtualDiceGame : Boolean) : Integer;
Var
BowlDieResult : Integer;
Begin
If VirtualDiceGame
Then BowlDieResult := Random(6) + 1
Else
Begin
Writeln('Please roll the bowling die and then enter your result.');
Writeln;
Writeln('Enter 1 if the result is a 1');
Writeln('Enter 2 if the result is a 2');
Writeln('Enter 3 if the result is a 4');
Writeln('Enter 4 if the result is a 6');
Writeln('Enter 5 if the result is a 0');
Writeln('Enter 6 if the result is OUT');
Writeln;
Write('Result: ');
Readln(BowlDieResult);
Writeln;
End;
RollBowlDie := BowlDieResult;
End;
I have tried putting this in, but the message error message didnt come up, and the program crashed when trying in a letter.
Function RollBowlDie(VirtualDiceGame : Boolean) : Integer;
Var
BowlDieResult : Integer;
Begin
If VirtualDiceGame
Then BowlDieResult := Random(6) + 1
Else
Begin
Repeat
Writeln('Please roll the bowling die and then enter your result.');
Writeln;
Writeln('Enter 1 if the result is a 1');
Writeln('Enter 2 if the result is a 2');
Writeln('Enter 3 if the result is a 4');
Writeln('Enter 4 if the result is a 6');
Writeln('Enter 5 if the result is a 0');
Writeln('Enter 6 if the result is OUT');
Writeln;
Write('Result: ');
Try
Readln(BowlDieResult)
Except
Writeln('Not a valid number')
End;
Writeln;
Until (BowlDieResult >= 1) and (BowlDieResult <= 6);
End;
RollBowlDie := BowlDieResult;
End;
I's not sure how to solve the question, any help would be appreciated greatly!
Probably you need to read a string or a char-typed variable instead of an integer one, and then convert the string/char to integer in an controlled way.
Of course it crashes if you type in a letter ... you're specifically asking to
read an integer, and a letter isn't an integer.
Before commenting more on that issue, why not just say:
writeln ('Please enter the number rolled, or 0 if it is an OUT: ');
rather than having 6 writelns? Also, what if a 3 or 5 was rolled (you're only
giving (somewhat odd) directions for the values 1, 2, 4, 6, and 0 ... leaving
out 3 and 5. Keep in mind that you can't get a 0 from "BowlDieResult := Random(6) + 1".
How do you intend the user to indicate "stop" if you're looping until you have
a value between 1 and 6?
Back to the "how do I read a letter" question...
Use a variable of type "char" (or "packed array of char") to read arbitrary text ...
then, compare the character read to '1', '2', ..., '6', or (say) 'Q' (for Quit).
E.g.:
var
answer : char;
attempts : integer; {prevent infinite loop}
done : boolean;
attempts := 0;
saw_quit := false;
done := false; {loop until we get a good number or a QUIT command}
{Or until 9 attempts have been made to enter a #. }
while not done do
begin
writeln ('Please enter a number (1..6) or Q to quit: ');
readln (answer);
if answer in ['1'..'6'] then
begin {we got a number in range 1..6...}
BowlDieResult := ord (answer) - ord ('0'); {convert char to int}
done := true;
end
else if answer in ['Q', 'q'] then {upper or lower case :) }
begin
saw_quit := true;
done := true;
end
else
begin
writeln ('Sorry, that is not a number from 1 to 6 or a "Q"!');
attempts := attempts + 1;
if attempts > 9 then
begin
writeln ('Sorry, too many mistakes ... assuming QUIT');
saw_quit := true;
done := true;
end;
end;
end; {while not done}
Note: the above not tested for compilation ... I NEVER use Pascal's built-in I/O,
for performance and reliability reasons, so I'm rusty with it.
Note: see http://www.allegro.com/papers/htpp.html
for some philosophy of Pascal programming.
Stan

How to keep 2 decimal places in Delphi?

I have selected columns from a database table and want this data with two decimal places only. I have:
SQL.Strings = ('select '#9'my_index '#9'his_index,'...
What is that #9?
How can I deal with the data I selected to make it only keep two decimal places?
I am very new to Delphi.
#9 is the character with code 9, TAB.
If you want to convert a floating point value to a string with 2 decimal places you use one of the formatting functions, e.g. Format():
var
d: Double;
s: string;
...
d := Sqrt(2.0);
s := Format('%.2f', [d]);
function Round2(aValue:double):double;
begin
Round2:=Round(aValue*100)/100;
end;
#9 is the tab character.
If f is a floating-point variable, you can do FormatFloat('#.##', f) to obtain a string representation of f with no more than 2 decimals.
For N Places behind the seperator use
function round_n(f:double; n:nativeint):double;
var i,m : nativeint;
begin
m := 10;
for i := 1 to pred(n) do
m := m * 10;
f := f * m;
f := round(f);
result := f / m;
end;
For Float to Float (with 2 decimal places, say) rounding check this from documentation. Gives sufficient examples too. It uses banker's rounding.
x := RoundTo(1.235, -2); //gives 1.24
Note that there is a difference between simply truncating to two decimal places (like in Format()), rounding to integer, and rounding to float.
Nowadays the SysUtils unit contains the solution:
System.SysUtils.FloatToStrF( singleValue, 7, ffFixed, 2 );
System.SysUtils.FloatToStrF( doubleValue, 15, ffFixed, 2 );
You can pass +1 TFormatSettings parameter if the requiered decimal/thousand separator differ from the current system locale settings.
The internal float format routines only work with simple numbers > 1
You need to do something more complicated for a general purpose decimal place limiter that works correctly on both fixed point and values < 1 with scientific notation.
I use this routine
function TForm1.Flt2str(Avalue:double; ADigits:integer):string;
var v:double; p:integer; e:string;
begin
if abs(Avalue)<1 then
begin
result:=floatTostr(Avalue);
p:=pos('E',result);
if p>0 then
begin
e:=copy(result,p,length(result));
setlength(result,p-1);
v:=RoundTo(StrToFloat(result),-Adigits);
result:=FloatToStr(v)+e;
end else
result:=FloatToStr(RoundTo(Avalue,-Adigits));
end
else
result:=FloatToStr(RoundTo(Avalue,-Adigits));
end;
So, with digits=2, 1.2349 rounds to 1.23 and 1.2349E-17 rounds to 1.23E-17
This worked for me :
Function RoundingUserDefineDecaimalPart(FloatNum: Double; NoOfDecPart: integer): Double;
Var
ls_FloatNumber: String;
Begin
ls_FloatNumber := FloatToStr(FloatNum);
IF Pos('.', ls_FloatNumber) > 0 Then
Result := StrToFloat
(copy(ls_FloatNumber, 1, Pos('.', ls_FloatNumber) - 1) + '.' + copy
(ls_FloatNumber, Pos('.', ls_FloatNumber) + 1, NoOfDecPart))
Else
Result := FloatNum;
End;
Function RealFormat(FloatNum: Double): string;
Var
ls_FloatNumber: String;
Begin
ls_FloatNumber:=StringReplace(FloatToStr(FloatNum),',','.',[rfReplaceAll]);
IF Pos('.', ls_FloatNumber) > 0 Then
Result :=
(copy(ls_FloatNumber, 1, Pos('.', ls_FloatNumber) - 1) + '.' + copy
(ls_FloatNumber, Pos('.', ls_FloatNumber) + 1, 2))
Else
Result := FloatToStr(FloatNum);
End;

Resources