I am trying to write a program which will do multiply/divide the same variable without it resetting(sorry if it is not explained well). I will show an example if what I want
var
selection:integer
writeln ('Select a number');
readln (selection);
writeln (selection*10);
writeln (selection/5);
What I want to happen is for the selection variable to be multiplied by 10, then divided by 5. e.g. if the user enters 5, it will be multiplied by 10, then divided by 5. So I should get 5*10=50, then 50/5=10. But instead it will do 5*10, and then 5/5 separately.How would I do it so that it does the multiplication, and then the division to the new number made from the multiplication?
You aren't modifying the variable. You need to write it like this:
selection := selection * 10;
writeln(selection);
selection := selection div 5;
writeln(selection);
Note also that you need to use integer division, div, rather than real division, /.
Related
I need to print values that are in a matrix, these may vary from integer to real. As an example a matrix that my program use, named kernel, is shown below:
kernel[0,0]:= 1/16;
kernel[0,1]:= 2/16;
kernel[0,2]:= 1/16;
kernel[1,0]:= 2/16;
kernel[1,1]:= 4/16;
kernel[1,2]:= 2/16;
kernel[2,0]:= 1/16;
kernel[2,1]:= 2/16;
kernel[2,2]:= 1/16;
the issue comes when printing each of them, because I couldn't find a way to print a number like 1/16 in a easy-to-read way, the program displays something like 6.2500000000000000000000000000E-2 which is OK but I would prefer to have something more aesthetic like 0.0625 or even better 1/16. Does anyone acknowledge a way of formatting that allows me to do so?
Each array element holds the value of the fraction.
To write the value as a fraction you can simply calculate the numerator as the product of the array element and the denominator.
I prefer to use the Format() function for display formatting.
Given the array you show, two index variables, a and b and the denominator
denominator := 16;
for a := 0 to 2 do
for b := 0 to 2 do
begin
s := format('kernel[%d,%d] = %d/%d',[a,b,round(kernel[a,b]*denominator),denominator]);
memo1.Lines.Add(s);
end;
The intuitive answer would be that the loop is never entered. And this seems to be case in all tests I could come up with. I'm still anxious and always test it before entering the loop.
Is this necessary?
No, it is not necessary.
The documentation clearly states :
for counter := initialValue to finalValue do statement
or:
for counter := initialValue downto finalValue do statement
...
If initialValue is equal to finalValue, statement is executed exactly once. If initialValue is greater than finalValue in a for...to statement, or less than finalValue in a for...downto statement, then statement is never executed.
There is no need for anxiety.
If we want to examine further what happens, let's make a few examples. Consider first :
program Project1;
{$APPTYPE CONSOLE}
var
i : integer;
begin
for i := 2 to 1 do WriteLn(i);
end.
This produces a compiler hint:
[dcc32 Hint] Project1.dpr(6): H2135 FOR or WHILE loop executes zero times - deleted
So the compiler will simply throw away a loop with constants that produce no loop iterations. It does this even with optimizations turned off - no code is produced for the loop at all.
Now let's be a bit more clever :
program Project1;
{$APPTYPE CONSOLE}
var
i, j, k : integer;
begin
j := 2;
k := 1;
for i := j to k do WriteLn(i);
end.
This actually compiles the loop. The output is as below:
Project1.dpr.8: for i := j to k do WriteLn(i);
004060E8 A1A4AB4000 mov eax,[$0040aba4] {$0040aba4 -> j = 2}
004060ED 8B15A8AB4000 mov edx,[$0040aba8] {$0040aba8 -> k = 1}
004060F3 2BD0 sub edx,eax {edx = k - j = -1}
004060F5 7C2E jl $00406125 {was k-j < 0? if yes, jmp to end.}
004060F7 42 inc edx {set up loop}
004060F8 8955EC mov [ebp-$14],edx
004060FB A3A0AB4000 mov [$0040aba0],eax
00406100 A118784000 mov eax,[$00407818] {actual looped section}
00406105 8B15A0AB4000 mov edx,[$0040aba0]
0040610B E8E8D6FFFF call #Write0Long
00406110 E8C3D9FFFF call #WriteLn
00406115 E8EECCFFFF call #_IOTest
0040611A FF05A0AB4000 inc dword ptr [$0040aba0] {update loop var}
00406120 FF4DEC dec dword ptr [ebp-$14]
00406123 75DB jnz $00406100 {loop ^ if not complete}
Project1.dpr.9: end.
00406125 E88EE1FFFF call #Halt0
So, the very first thing a loop does is to check whether it needs to execute at all. If the initial is greater than the final (for a for..to loop) then it skips straight past it entirely. It doesn't even waste the cycles to initialize the loop counter.
There are some edge-cases in which you may be surprised to discover that the code does unexpectedly enter the loop. And still other cases where you may be tempted to pre-check whether to call the loop. But before I get into those details, I want to try impress on you the importance of not pre-checking your loop with an if condition.
Every line of code, no matter how easy to understand draws attention. It's more to read and more to confirm is correct. So if it's not important, or if it's technically redundant: it's best left out.
A for loop is conceptually translated as follows:
Initialise loop index to starting value.
If iteration constraint is valid (e.g. Index <= EndValue in case of forward loop):
Perform iteration (code within loop block/statement)
Perform loop control operations (increment loop index)
Repeat 2
Otherwise continue at first instruction after loop.
The way in which Step 2 is checked, makes an extra if condition before the loop completely redundant.
So if you (or another developer) is later maintaining code with a redundant if condition, they're left to wonder:
Is the line correct?
It seems redundant; is there a special condition it's trying to handle?
If it currently serves no purpose, perhaps it was intended to prevent calling the loop on a different condition?
In simple case, redundant lines of code can create some confusion. In more complex cases, they can result in whole new sections of irrelevant code being developed; that tries to cater for irrelevant scenarios implied by legacy redundant code.
Recommendation: Stamp out redundant code as much as possible. Including redundant pre-checks for "should the loop execute at all".
The most important benefit of stamping out redundant code is that: it correctly draws attention to peculiar cases whenever special handling actually is required.
There are 2 potential pitfalls, and the first is the more dangerous one as it deals with implicit type conversion. So it may not always be easy to detect. The following code was tested on rextester using fpc, but I have verified the same issue on Delphi 2007 / 2009 in the past.
//fpc 2.6.2
program UnexpectedForIteration;
{$MODE DELPHI}
{ Ensure range-checking is off. If it's on, a run-time error
prevents potentially bad side-effects of invalid iterations.}
{$R-,H+,W+}
var
IntStart, IntEnd, IntIndex: Integer;
UIntStart, UIntEnd, UIntIndex: Cardinal;
IterCount: Integer;
begin
Writeln('Case 1');
IntStart := High(Integer) - 1;
IntEnd := -IntStart;
UIntStart := Cardinal(IntStart);
UIntEnd := Cardinal(IntEnd);
{This gives a clue why the problem occurs.}
Writeln('From: ', IntStart, ' To: ', IntEnd);
Writeln('From: ', UIntStart, ' To: ', UIntEnd, ' (unsigned)');
Writeln('Loop 1');
IterCount := 0;
for IntIndex := IntStart to IntEnd do Inc(IterCount);
Writeln(IterCount);
Writeln('Loop 2');
IterCount := 0;
{ The loop index variable is a different type to the initial &
final values. So implicit conversion takes place and:
IntEnd **as** unsigned is unexpectedly bigger than IntStart }
for UIntIndex := IntStart to IntEnd do Inc(IterCount);
Writeln(IterCount, ' {Houston we have a problem}');
Writeln();
Writeln('Case 2');
UIntStart := High(Cardinal) - 2;
UIntEnd := 2;
IntStart := Integer(UIntStart);
IntEnd := Integer(UIntEnd);
{This gives a clue why the problem occurs.}
Writeln('From: ', UIntStart, ' To: ', UIntEnd);
Writeln('From: ', IntStart, ' To: ', IntEnd, ' (signed)');
Writeln('Loop 3');
IterCount := 0;
for UIntIndex := UIntStart to UIntEnd do Inc(IterCount);
Writeln(IterCount);
Writeln('Loop 4');
IterCount := 0;
{ The loop index variable is a different type to the initial &
final values. So implicit conversion takes place and:
UIntStart **as** signed is unexpectedly less than UIntEnd }
for IntIndex := UIntStart to UIntEnd do Inc(IterCount);
Writeln(IterCount, ' {Houston we have a problem}');
end.
The output is as follows:
Case 1
From: 2147483646 To: -2147483646
From: 2147483646 To: 2147483650 (unsigned)
Loop 1
0
Loop 2
5 {Houston we have a problem}
Case 2
From: 4294967293 To: 2
From: -3 To: 2 (signed)
Loop 3
0
Loop 4
6 {Houston we have a problem}
In many cases the problem is resolved by ensuring the same types are used for loopIndex, initialValue and finalValue. As this means there won't be an implicit type conversion, and the loop will reliably iterate as the initialValue and finalValue would suggest.
It would be easier if the compiler emits appropriate warnings for implicit type conversion in for loops. Unfortunately fpc didn't; I don't recall whether Delphi 2007/2009 does; and have no idea whether any recent versions do.
However, the preferred approach would be to favour container iteration syntax (pushing responsibility for 'correct' iteration on the enumerators). E.g.: for <element> in <container> do ...;. This should not iterate empty containers provided the enumerator's methods are implemented correctly.
The only time I'd say a pre-check is worth considering is:
when for in is not feasible for some reason
and the loop index needs to be zero-based
and support large unsigned integers (High(Integer) < index < High(Cardinal))
because this leaves no space for a reliable sentinel less than all possible initial values.
Even in this case, consider using an Int64 loop index instead of if (initialValue <= finalValue) then for ....
The second pitfall involves what I would in any case consider to be a design flaw. So the problem can be avoided entirely by rather being aware of this design consideration. It is demonstrated in code that looks as follows:
if Assigned(AnObject) then
for LIndex := 0 to AnObject.Count - 1 do ...;
In this case the if condition may in fact be necessary as a result of dubious design. Certainly, if AnObject hasn't been created, you do not want to access its Count property/method. But the dubious aspect of the design is the fact that you're uncertain whether AnObject exists. Yes, you may have employed a lazy-initialisation pattern. But it doesn't change the fact that in the above code, there's no way to differentiate between: "zero iterations" because AnObject doesn't exist or because AnObject.Count = 0.
I'd like to point out that when code has many redundant if Assigned(AnObject) then (or similar) lines, it leads to one of the problems I described in section 1. Local code caters for 2 possibilities. And by extension, client code also caters for 2 possibilities. And by induction, this problem eventually leaks throughout the code-base.
The solution is to first and foremost limit the cases where existence of AnObject is uncertain.
It's much easier to ensure an empty object with Count = 0 is guaranteed to be created (typically only affecting a small number of places in code).
It's far more work to deal with the ripple effects of a large number of places where the object might not exist yet; yielding 2 possible states and code paths.
If lazy-initialisation is required, try to ensure the code surface where existence is optional is kept as small as possible.
Write a program to convert an integer number to its hexadecimal representation without using inbuilt functions.
Here is my code, but it is not working. Can anyone tell where is the mistake?
It is giving an error:
"Project raised exception class EAccessViolation with message 'Access violation at address 00453B7B in module 'Project.exe'.Write of address FFFFFFFF'.Process stopped.Use Step or Run to continue."
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,Forms,
Dialogs;
type
TForm1 = class(TForm)
end;
function hexvalue(num:Integer):Char;
var
Form1: TForm1;
implementation
{$R *.dfm}
function hexvalue(num:Integer):Char;
begin
case num of
10: Result:='A';
11: Result:='B';
12: Result:='C';
13: Result:='D';
14: Result:='E';
15: Result:='F';
else Result:=Chr(num);
end;
end;
var
intnumber,hexnumber,actualhex:String;
integernum:Integer;
i,j,k:Byte;
begin
InputQuery ('Integer Number','Enter the integer number', intnumber);
integernum:=StrToInt(intnumber);
i:=0;
while integernum >= 16 do
begin
hexnumber[i]:=hexvalue(integernum mod 16);
integernum:= integernum div 16;
Inc(i);
end;
hexnumber[i]:= hexvalue(integernum);
k:=i;
for j:=0 to k do
begin
actualhex[j]:= hexnumber[i];
Dec(i);
end;
ShowMessage(actualhex);
end.
Since this obviously is a homework assignment, I don't want to spoil it for you and write the solution, but rather attempt to guide you to the solution.
User input
In real code you would need to be prepared for any mistake from the user and check that the input really is integer numbers only and politely ask the user to correct the input if erroneous.
Conversion loop
You have got that OK, using mod 16 for each nibble of integernum and div 16 to move to the next nibble, going from units towards higher order values.
Conversion of nibble to hex character
Here you go wrong. If you would have written out also the cases for 0..9, you could have got the case statement right. As others have commented, Chr() takes an ASCII code. However, using a case statement for such a simple conversion is tedious to write and not very efficient.
What if you would have a lookup table (array) where the index (0..15) directly would give you the corresponding hex character. That would be much simpler. Something like
const
HexChars: array[_.._] of Char = ('0',_____'F')
I leave it to you to fill in the missing parts.
Forming the result (hex string)
Your second major mistake and the reason for the AV is that you did not set the length of the string hexnumber before attempting to acess the character positions. Another design flaw is that you fill in hexnumber backwards. As a result you then need an extra loop where you reverse the order to the correct one.
There are at least two solutions to solve both problems:
Since you take 32 bit integer type input, the hex representation is not more than 8 characters. Thus you can preset the length of the string to 8 and fill it in from the lower order position using 8 - i as index. As a final step you can trim the string if you like.
Don't preset the length and just concatenate as you go in the loop hexnumber := HexChars[integernum mod 16] + hexnumber;.
Negative values
You did not in any way consider the possibility of negative values in your code, so I assume it wasn't part of the task.
First mistake : String are 1 indexed. Meaning that the index of their first character is 1 and not 0. You initialize "i" to 0 and then try to set hexnumber[i].
Second mistake : Strings might be dynamic, but they don't grow automatically. If you try to access the first character of an empty string, it won't work. You need to call SetLength(HeXNumber, NumberOfDigits). You can calculate the number of digits this way :
NumberOfDigits := Trunc(Log16(integernum)) + 1;
Since Log16 isn't really something that exists, you can either use LogN(16,integernum) or (Log(IntegerNum) / Log(16)) depending on what is available in your version of Delphi.
Note that this might return an invalid value for very, very large value (high INT64 range) due to rounding errors.
If you don't want to go that road, you could replace the instruction by
hexnumber := hexvalue(integernum mod 16) + hexnumber;
which would also remove the need to invert the string at the end.
Third Mistake : Using unsigned integer for loop variable. While this is debatable, the instruction
for I := 0 to Count - 1 do
is common practice in Delphi without checking Count > 0. When count = 0 and using an unsigned loop counter, you'll either get an integer overflow (if you have them activated in your project options) or you'll loop High(I) times, which isn't what you want to be doing.
Fourth mistake : already mentionned : Result:=Chr(num) should be replaced by something like Result := InttoStr(Num)[1].
Personally, I'd implement the function using an array.
HexArr : Array[0..15] of char = ('0', '1',...,'D','E','F');
begin
if InRange(Num, 0, 15) then
Result := HexArr[Num]
else
//whatever you want
end;
I'm getting the user to enter coefficients (as strings) for terms from a constant (e.g. 2) all the way up to a sextic (e.g. 3X^6).
The user enters each coefficient without the X-term attached to it, so 3X^6 is entered just as 3.
Upon clicking an okay button, the idea is to transfer the coefficients which are valid (checked using a RegEx expression) to a procedure ('CreateGraph') which actually creates the graph using TChart.
Upon clicking the okay button, a loop for i = 1 to 7 (number of coefficients) is used to check if each term is valid. The issue I am having is that I get a string conversion error when converting the coefficients in the CreateGraph procedure as the other coefficients except those with data in, are set to '', which TChart won't accept.
Here's the current procedure:
procedure TfrmGetFunction.btnAddFunctionClick(Sender: TObject);
var
i : integer; // Loop counter.
begin
for i := 1 to 7 do
begin
if CheckCoefficientBoxesValidInput(CoefficientEdit[i].CoEditBox) then
frmGraphingMode.CreateGraph(CoefficientEdit[i].CoEditBox);
end;
end;
Is the best way to just set the inactive coefficient edit boxes to '0'?
The (potential) issue I have with that is that when the user wants to enter another set of coefficients or comes back to the 'Enter Function' form, the values are all set to 0 which may be confusing.
The next issue (related to the first) that I am having, is that the CreateGraph procedure is called each time i is incremented, which means that a load of empty input boxes are passed, which TChart doesn't like.
Here's my current procedure:
var
i : integer; // Loop counter.
Coeff : array[1..7] of string;
begin
for i := 1 to 7 do
begin
Coeff[i] := CoefficientEdit[i].CoEditBox.Text;
if Coeff[i] = '' then
Coeff[i] := '0';
frmGraphingMode.CreateGraph(Coeff[i]);
end;
end;
What is the easiest way to solve this problem? I was thinking of having a boolean variable which is set to true when the loop is complete (i.e. i = 7 is when all the empty (if so) boxes would be filled in); is there a better way?
Simply check for the empty string and replace with '0'.
var
Coeff: string;
....
Coeff := CoefficientEdit[i].CoEditBox.Text;
if Coeff = '' then
Coeff := '0';
I'm assuming that CoEditBox is an edit control. If so then I would comment that you should not pass an edit control to CheckCoefficientBoxesValidInput and CreateGraph. Those functions should receive string arguments. You are making them needlessly coupled to a particular GUI design.
Perhaps this is the root cause of your problems. You comment that it is confusing for the edit controls to be changed to contain zeros. Well, you don't need to, and should now, change the edit controls. Separate the GUI from the charting. Don't pass around edit controls. Pull the contents from the controls, optionally process it, and pass it on.
Finally, instead of using a regex to check if a value is a number, call TryStrToFloat.
I am trying to build a function/check to prevent wrong inputs from keyboard and I am a little bit lost here.
function ReadInputs : integer;
var
number : integer;
begin
repeat
Write('Set random number (1-10): ');
Readln(number);
if NOT((number <= 10) AND (number >= 1)) then
begin
Writeln('Error! Type 1-10!');
end;
until (number >= 1) AND (number <= 10);
result := column;
end;
How to prevent from any other character to be input except numbers 1-10? Why only numbers define in my function is not enough even when I set integer? When I type for example "A" it crash, so what is the right way? Thank you.
As it stands your program will fail with an error if the user inputs something that cannot be converted to an integer. That's because the variable that you passed to Readln is typed as an Integer. That is effectively an assertion that the user enters a number. But you want to be more flexible than that and allow the user to recover from non-numeric input.
What you need to do is read a string. This will always succeed. Then you can decide how to handle that string. For example you would try to convert to integer, and if that succeeded, perform further validity checks.
Perhaps like this:
var
Input: string;
Num: Integer;
....
Readln(Input);
if TryStrToInt(Input, Num) then
// perform checks on Num, etc.
else
// handle error: the value input was not numeric
You've already had a good answerfrom David H, but a little more explanation might help.
The ReadLn() procedure dates from before applications had GUIs and doesn't really restrict what the user can type in; the user might just press [return] or type characters that aren't digits (or +/-). ReadLn(AnInteger) will succeed if what the user types happens to convert to an integer, otherwise it fails.
On the other hand, Readln(AString) will always succeed, and the problem then is just how to check that it represents an integer, and DH's answer shows you how to do that.
In case you're wondering, a GUI application, you can control what characters an edit control will accept, e.g. by using a TMaskEDit, which allows you specify what character patterns are acceptable (e.g 6 digits and nothing else) - if the user types something which doesn't match the mask, the edit control doesn't accept it. However, even if you use a TMaskEdit, it's best to check that what's been typed in actually converts to the number type you're wanting.
Or you could use this on the OnKeyPress event:
if NOT(key in['0'..'9', #8]) then
key := #0;