Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by Marat1961

  1. Marat1961

    Parsing Text search expression

    You can use Coco/R, as I have seen an attributive grammar for a similar sql-like language. Not long ago I made a port on Delphi. I have been using it for a long time and quite actively in my projects.
  2. I completely agree that this approach has a right to life. If the client code is written by you, if you never make mistakes. That is, if the target, for example, was allocated on the heap, if the target is not part of a packed record, etc. But if you write that your procedure guarantees atomicity (judging by its name). I think a check will not hurt. From the point of minimizing the code, it is better to insert checks at the beginning of the procedure. Well, at least observe the minimum decency and insert Assert into debug mode.
  3. Contract programming. The simplest version of the contract is preconditions - requirements that must be met before a specific action. The method must check the validity of the passed parameters. https://en.wikipedia.org/wiki/Design_by_contract
  4. I also find it interesting to use the function function InterlockedSetDouble(Value: double): double; begin if (@Result and $7) = 0 then Result := Value else ...
  5. It seems naive to me to hope that var parameter will be aligned. At a minimum, I would insert a check
  6. Due to the causal relationship, it seemed logical to me to discuss here. 1. The atomicity of the data assignment operation is ensured if the data is aligned on the double word boundary. 2. The data is aligned if ..
  7. don't worry, be happy When passed through the stack, parameters will be aligned on the 8-byte boundary if the parameters are passed by value and one of the following conditions is met: 1. all parameters are multiples of 8 bytes 2. optimization enabled 3. 64 bit mode Therefore, I would exclude passing by var and passing two double parameters. This would ensure that the values are aligned in memory.
  8. He who is forewarned is armed. For a long time I was looking for an error when using the Windows API due to the fact that the parameter was not aligned on the boundary of a 32-bit word. procedure InterlockedSetDouble(var target: double; flag: Byte; Value: double); I think now Value will be misaligned
  9. The variable must be allocated on the heap. If it is a local variable, we have no guarantee that it will be aligned. By the way, under certain conditions, the parameter passed by value may also be misaligned.
  10. Marat1961

    Hashing Street Addresses ?

    If you want to get hash of an object by key fields, it is convenient to serialize these fields, e.g. in TMemoryStream or even string. Then use reliable hash function, for example SHA-3. Fields can be numbered, empty values can be skipped '1:France;3:Paris'. For strings, a function that takes string length in characters into account when calculating the hash is useful. For floating point numbers, it is better to use an algorithm that hashes the exponent and the mantissa of the number separately. If it's an object or a record, sometimes it makes sense to write your own function that hashes selected key fields of the object.
  11. Marat1961

    Hashing Street Addresses ?

    There can be several addresses in a house and they all have the same geodata.
  12. The search speedup for hashmaps in this case is ~ 1/N, where N is the size of the table. As long as the table is not completely filled with less than < 0.7 the table works well, and then comes performance degradation. In such cases, the table size is increased and all data is moved to the new table. This takes extra time and also means that while you do this, your system will not be able to serve clients. In my opinion, up to about 16 elements, it is better to use a regular unsorted list and a linear search. Then it makes sense to use either a TList with sorting each time a new key is added, ~ N * log2(N) for quicksort, or a tree where search and insertion with order maintenance is an inexpensive log2(N). Advantages of hashmaps. Search time for hashmap includes: hash generation + 1 to m equality comparisons. Ideal hash function: 1. must be fast 2. Does not create collisions (does not generate the same key for different keys). I have compared many hash functions in my time and realized that even the simplest ones provide good results on real data. I have tested it on a database of addresses with about a million entries and for a client base with about 500,000 entries. The algorithms included md5, sha-2, sha-3, src32, multiplicative hash. function HashMultiplicative(const key: PByte; Size: Cardinal): Cardinal; var i, hash: Cardinal; p: PByte; begin hash := 5381; p := key; for i := 1 to Size do begin hash := 33 * hash + p^; Inc(p); end; Result := hash; end; For strings, a function that takes string length in characters into account when calculating the hash is useful. For floating point numbers, it is better to use an algorithm that hashes the exponent and the mantissa of the number separately. If it's an object or a record, sometimes it makes sense to write your own function that hashes selected key fields of the object. I like hash table implementations with chains. I usually know the approximate number of objects in the system and can immediately set the required input table size N. This will require a bit more memory, but you know right away what the speedup will be and there will be no time wasted on dynamically increasing the table. There is no point in increasing the size of the table much more than N. Since the input index is determined by the search index_input := hash mod N; You can't choose a table size multiple of a byte, it increases the crowding of data in the table. For many hashing algorithms, if you choose a size other than a prime number, the probability of collisions will increase and it will degrade the statistics.
  13. After one of the releases of our program was hacked about 15 years ago and posted the hacked version on FTP. We protect our code with a protector. I think our company uses Enigma now. There have been no more such hacks since then. At least the code must be digitally signed and its integrity must be verified. If something goes wrong, we check some flags somewhere and the program changes its behavior (works incorrectly). It may crash after a while, modal windows stop working well, etc. Separate out the fact of tamper detection and where things will work differently should be placed as far as possible in time and scattered across the code.
  14. tPolar2D = record Radius: Double; azimuth: Double; end; forward; //keyword just to say there are methods to be defined later In my opinion, this is not the most successful design. A radical solution is needed. It is much better to add a namespace. And inside the namespace, allow to refer to any declarations, regardless of the order of their declaration.
  15. PPoint2D = ^TPoint2D; PPolar2D = ^TPolar2D; constructor TPolar2D.From(const Pt: PPoint2D); constructor TPolar2D.From(X, Y: Double); constructor TPoint2D.From(const Pt: PPolar2D); constructor TPoint2D.From(Radius, Azimuth: Double); PNode = ^TNode; TNode = record next: PNode; end; var ppt: TPolar2D; cpt: TPoint2D; begin ppt := TPolar2D.From(@cpt); end.
  16. I certainly understand that many people did not program on a pure Pascal. Use pointers and you will be happy. Pointers to a record can be declared before the record is declared. Also if you pass a record as a parameter, there is no need to pass the value as it is extremely inefficient and the recording value is copied to the stack. Transmit the record by var or by const. PPoint2D = ^tPoint2D;
  17. Marat1961

    Having fun with Delphi

    System.IOUtils.TPath used for operating the OS file system. File and directory names. At first I missed that the topic was about URLs and I decided that it was about files. The URL is designed to work with Internet entities.
  18. I would use the MCV pattern. The user interface must be subscribed to change the data model. Receiver and consumer must be processes. When the model changes, notify the user interface about the need to update the presentation. Supplier => Consumer => Model MainForm.Refresh; The timer, by the way, is useful in case of a group of changes. So that there is no fuss under the client, it is useful not to draw everything at once, but with some delay of at least 0.2 - 0.5 seconds. procedure TMainForm.RefreshTimerTimer(Sender: TObject); begin RefreshTimer.Enabled: = False; Refresh; end; procedure TMainForm.ModelChanged(Sender: TObject); begin RefreshTimer.Rearm; end;
  19. It was first done well in this book, Hoare, C. A. R. Communicating sequential processes I have a book "Patterns in Java. A Catalog of Reusable Design Patterns Illustrated with UML | Grand Mark". This book describes the Producer-Consumer pattern, in my opinion this is your case. There are code examples for the queue.
  20. This code was definitely not passed through the autoformat. You still don't know what the Soviet norm - control is!
  21. You just need to configure the auto format according to the formatting standard. This format is usually the default. If you think a little, then the following conclusion follows from here: Delphi has only one correct coding standard, and all the others are wrong. When you invite other people to see the code, don't surprise them with your absolutely amazing and most perfect style of code formatting.
  22. Borland / CodeGear / Embarcadero / Jedi coding standard. You can see for example how the formatting of System.Classes
  23. Marat1961

    TMapView Draw route

    Let's try to draw a straight line from point A to point B. Put a button on the form and write in the onClick handler: TPoint = record x, y: Integer; end; procedure DrawLine(A, B: TPoint); begin Form1.Canvas.MoveTo(A.x, A.y); Form1.Canvas.LineTo(B.x, B.y); end; A.x: = 0; A.y: = 0; B.x: = 100; B.y: = 10; DrawLine(A, B);
  24. Marat1961

    TMapView Draw route

    I think that's how it will work! DrawLine (A, B);
  25. Marat1961

    Multiple two UInt64 modulo

    Where will your code in the procedure be faster than the same code generated by the compiler. As far as I understand, the functionality of the code is the same, but the overhead of calling the procedure is added. As a result, if we calculate everything, we lose in performance.