* * * *

Privacy Policy

Blog italiano

Clicca qui se vuoi andare al blog italiano su Lazarus e il pascal.

Forum ufficiale

Se non siete riusciti a reperire l'informazione che cercavate nei nostri articoli o sul nostro forum vi consiglio di visitare il
Forum ufficiale di Lazarus in lingua inglese.

Lazarus 1.0

Trascinare un file nel programma
DB concetti fondamentali e ZeosLib
Recuperare codice HTML da pagina web
Mandare mail con Lazarus
Stabilire il sistema operativo
Esempio lista in pascal
File INI
Codice di attivazione
Realizzare programmi multilingua
Lavorare con le directory
Utilizzare Unità esterne
TTreeView
TTreeview e Menu
Generare controlli RUN-TIME
LazReport, PDF ed immagini
Intercettare tasti premuti
Ampliare Lazarus
Lazarus e la crittografia
System Tray con Lazarus
UIB: Unified Interbase
Il file: questo sconosciuto
Conferma di chiusura di un applicazione
Liste e puntatori
Overload di funzioni
Funzioni a parametri variabili
Proprietà
Conversione numerica
TImage su Form e Panel
Indy gestiore server FTP lato Client
PopUpMenu sotto Pulsante (TSpeedButton)
Direttiva $macro
Toolbar
Evidenziare voci TreeView
Visualizzare un file Html esterno
StatusBar - aggirare l'errore variabile duplicata
Da DataSource a Excel
Le permutazioni
Brute force
Indy 10 - Invio email con allegati
La gestione degli errori in Lazarus
Pascal Script
Linux + Zeos + Firebird
Dataset virtuale
Overload di operatori
Lavorare con file in formato JSON con Lazarus
Zeos ... dietro le quinte (prima parte)
Disporre le finestre in un blocco unico (come Delphi)
Aspetto retrò (Cmd Line)
Lazarus 1.0
Come interfacciare periferica twain
Ubuntu - aggiornare free pascal e lazarus
fpcup: installazioni parallele di lazarus e fpc
Free Pascal e Lazarus sul Raspberry Pi
Cifratura: breve guida all'uso dell'algoritmo BlowFish con lazarus e free pascal.
Creare un server multithread
guida all'installazione di fpc trunk da subversion in linux gentoo
Indice
DB concetti fondamentali e connessioni standard
Advanced Record Syntax
DB concetti fondamentali e DBGrid
DB concetti fondamentali e TDBEdit, TDBMemo e TDBText
Advanced Record Syntax: un esempio pratico
Superclasse form base per programmi gestionali (e non)
Superclasse form base per programmi gestionali (e non) #2 - log, exception call stack, application toolbox
Superclasse form base per programmi gestionali (e non) #3 - traduzione delle form
Superclasse form base per programmi gestionali (e non) #4 - wait animation
Un dialog per la connessione al database:TfmSimpleDbConnectionDialog
Installare lazarus su mac osx sierra
immagine docker per lavorare con lazarus e free pascal
TDD o Test-Driven Development
Benvenuto! Effettua l'accesso oppure registrati.
Aprile 19, 2024, 01:40:28 am

Inserisci il nome utente, la password e la durata della sessione.

402 Visitatori, 0 Utenti

Autore Topic: [RISOLTO] Da intero a virgola mobile a stringa  (Letto 722 volte)

AlexLazarus

  • Jr. Member
  • **
  • Post: 91
  • Karma: +1/-0
[RISOLTO] Da intero a virgola mobile a stringa
« il: Gennaio 08, 2023, 10:24:54 am »
Sicuramente mi sto perdendo in un bicchier d'acqua, anche se non capisco dove sbaglio.
Dunque...

1) "Come voi ben sapete" (cit.) 75 diviso 2 =  37,5

2) Assegno alla variabile INTERA MioNumero il valore 75:

Var MioNumero : Integer;
...
MioNumero:= 75;
MioNumero:= MioNumero / 2;


Ovviamente(!) Lazarus s'incacchia; e si incacchia pure se modifico Integer con LongInt.
Accetta - altrettanto ovviamente - solo se dichiaro come Real. E fin qui, tutto OK.

3) Ma se io voglio partire da una variabile intera (p.e. una delle proprietà di tipo Integer per un qualsiasi oggetto) come posso effettuare una divisione che fornisce un risultato con decimali e (soprattutto) convertirlo in una stringa da visualizzare in un ShowMessage?


« Ultima modifica: Gennaio 09, 2023, 08:59:18 am da AlexLazarus »

bonmario

  • Hero Member
  • *****
  • Post: 1300
  • Karma: +10/-1
Re:Da intero a virgola mobile a stringa
« Risposta #1 il: Gennaio 08, 2023, 11:05:48 am »
Ciao,
non sono sicuro di aver capito la domanda, in ogni caso, "FloatToStr" converte un numero con decimali in stringa. Se vuoi, col secondo parametro gli dici come formattare il numero.

Ciao, Mario

giacomarko

  • Full Member
  • ***
  • Post: 105
  • Karma: +6/-0
Re:Da intero a virgola mobile a stringa
« Risposta #2 il: Gennaio 08, 2023, 01:32:34 pm »
in alternativa puoi usare la funzione Round (che esegue un arrotondamento del valore float) e restituisce un int64,

questo, se vuoi arrotondare il numero, rispettando il valore decimale,  quindi 75.89 diventa 76

viceversa..

se vuoi solo la parte intera, fregandotene se il valore era 75,89 oppure 75,02

puoi usare Trunc, che ritorna un Int64 del solo valore 75

m
m
SO: W11
Release Lazarus: 3.0 del 2023.12.17 win32/win64
Versione FPC: 3.2.2
DB: MySQL 5.0, MSAccess

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:Da intero a virgola mobile a stringa
« Risposta #3 il: Gennaio 08, 2023, 02:00:42 pm »
La divisione con risultato intero deve essere effettuata tramite la funzione DIV:

Codice: [Seleziona]
var
a, b, c: cardinal;

a := b div c;

La problematica di gestione dei numeri è costante ed è stata già affronta più volte nel forum.

Uno dei trucchi è quello di avere i numeri "moltiplicati per il fattore di precisione":

Codice: [Seleziona]
var a_cen, b, c: cardinal;

a_cen := (b*100) div c; //il risultato è in "centesimi" ....

Questa tecnica viene usata normalmente quando si ha a che fare con i sistemi di automazione industriale.

Di altro c'è la fantasia oltre che la normalità già spiegata dai precedenti post.

N.B.: ATTENZIONE ..... 2.0 / 2.0  potrebbe non fare sempre 1  :o

P.S.: non usare definizioni come real, float, o simili. Usa o "single" per la precisione singola o "double" per la precisione doppia che è anche quella più usata per la numerazione in virgola mobile.
« Ultima modifica: Gennaio 08, 2023, 02:04:23 pm da DragoRosso »
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

AlexLazarus

  • Jr. Member
  • **
  • Post: 91
  • Karma: +1/-0
Re:Da intero a virgola mobile a stringa
« Risposta #4 il: Gennaio 09, 2023, 08:58:35 am »
Tre risposte molto utili: non ricordavo FloatToString(!!)e avevo dimenticato il trucchetto di moltiplicare per 100 / 1000 per poi dividere nuovamente per 100 / 1000. Unica differenza: assegnare la variabile come Real (Cardinal genera errore).
Nello screenshot il mix dei consigli che hanno risolto il problema:
Codice: [Seleziona]
 procedure TForm1.Button1Click(Sender: TObject);
Var Sinistra: Integer;
Var Sin_decimale: Real; // NO Cardinal;

begin
Sinistra:= Button1.Left; // Valore Intero (proprietà .Left)
Sin_decimale:= ((Sinistra*1000) div 3) / 1000; // Variabile Real
ShowMessage('Risultato finale: ' + FloatToStr(Sin_decimale));
end;
                                                     

AlexLazarus

  • Jr. Member
  • **
  • Post: 91
  • Karma: +1/-0
Re:[RISOLTO] Da intero a virgola mobile a stringa
« Risposta #5 il: Gennaio 09, 2023, 09:13:29 am »
A proposito di Real, Single, Double, una cosa non mi torna. Non dovrebbe essere il contrario? (doppia precisione visualizza meno cifre decimali di singola precisione)?

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2870
  • Karma: +20/-4
Re:[RISOLTO] Da intero a virgola mobile a stringa
« Risposta #6 il: Gennaio 09, 2023, 09:28:59 am »
il single viene mappato in memoria con 4 bytes mentre il double con 8
quindi, semplificando, il double ha il doppio delle cifre significative a disposizione rispetto al single

guarda questo specchietto, chiarisce molti dubbi
https://www.freepascal.org/docs-html/ref/refsu5.html
Imagination is more important than knowledge (A.Einstein)

AlexLazarus

  • Jr. Member
  • **
  • Post: 91
  • Karma: +1/-0
Re:[RISOLTO] Da intero a virgola mobile a stringa
« Risposta #7 il: Gennaio 09, 2023, 09:44:38 am »
il single viene mappato in memoria con 4 bytes mentre il double con 8
quindi, semplificando, il double ha il doppio delle cifre significative a disposizione rispetto al single

Guardando lo screenshot precedente sembrerebbe esattamente il contrario. Oppure ho capito male?

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2870
  • Karma: +20/-4
Re:[RISOLTO] Da intero a virgola mobile a stringa
« Risposta #8 il: Gennaio 09, 2023, 10:14:06 am »
potrebbe dipendere dalla formattazione che hai usato per convertire in stringa
(floattostr sceglie il formato più conveniente in modo automatico)

con questo codice, il risultato lo vedi nell'allegato
forzando le cifre decimali a 16, il double è più preciso

Codice: [Seleziona]
procedure TForm1.Button1Click(Sender: TObject);
var s: single;
    d: double;
    sapp: string;
begin
  s := 92 / 3;
  d := 92 / 3;

  sApp := Format('Risultati:' + LineEnding +
                 'single = %20.16f' + LineEnding +
                 'double = %20.16f', [s, d]);

  ShowMessage(sapp);

end;         


Edit:
un altro controllo che puoi fare è quello di guardare il contenuto delle variabili a runtime con il debugger
ma ricorda che si tratta sempre di una conversione in stringa :)


« Ultima modifica: Gennaio 09, 2023, 10:20:15 am da nomorelogic »
Imagination is more important than knowledge (A.Einstein)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:[RISOLTO] Da intero a virgola mobile a stringa
« Risposta #9 il: Gennaio 09, 2023, 03:56:08 pm »
Da quello che ha postato @nomorelogic capisci che (2 / 2) potrebbe non fare 1.

Il single è visualizzato con le ultime cifre casuali, però vedi che anche nel double nelle due cifre finali qualcosa non torna... questo perchè le cifre significative in double sono circa 16 (e in formattazione ce ne sono 18 "%20.16f").

Ciao
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:[RISOLTO] Da intero a virgola mobile a stringa
« Risposta #10 il: Gennaio 09, 2023, 05:36:11 pm »
Create una nuova applicazione, metteteci due pulsanti e fate doppio click sui due pulsanti, poi sovrascrivete tutto col codice qui sotto (basta anche solo la parte implementation):

Codice: [Seleziona]
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private

  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }
type
  TConverterRec = packed record
    case Boolean of
      false: (ByteArray: array[0..7] of Byte);
      true: (FloatValue: Double);
    end;

var
  Pippo: TConverterRec;

procedure TForm1.Button1Click(Sender: TObject);
var d: double;
begin
  d := 0.43; // $85EB51B81E85DB3F  Valore 0,43 in double float
  //Pippo.FloatValue := d;
  Pippo.ByteArray[0] := $85;
  Pippo.ByteArray[1] := $EB;
  Pippo.ByteArray[2] := $51;
  Pippo.ByteArray[3] := $B8;
  Pippo.ByteArray[4] := $1E;
  Pippo.ByteArray[5] := $85;
  Pippo.ByteArray[6] := $DB;
  Pippo.ByteArray[7] := $3F;
  ShowMessage('Valore 0,43 = '+floattostr(Pippo.FloatValue));
  //Sommiamo 9 al primo byte byte (per verificare le cifre significative e la rappresentatività)
  inc(Pippo.ByteArray[0], 9);
  ShowMessage('Incremento ultima cifra di 9 del Valore 0,43 = '+floattostr(Pippo.FloatValue));
  //Non cambia .... dobbiamo sommare almeno 10 (9 di prima più 1) al primo byte byte (per verificare le cifre significative e la rappresentatività)
  inc(Pippo.ByteArray[0], 1);
  ShowMessage('Incremento ultima cifra di 10 del Valore 0,43 = '+floattostr(Pippo.FloatValue));
  //però ora facciamo i cattivi: proviamo a sommare il valore precedente (quello che anche se aveva 9 in più veniva visto come 0,43) a se stesso
  dec(Pippo.ByteArray[0], 1);
  ShowMessage('(Incremento ultima cifra di 9 del Valore 0,43) * 2 = '+floattostr(Pippo.FloatValue+Pippo.FloatValue));
  //OHH inciminciano i primi "disturbi ... ma il numero originale avrà anche lui questi problemi ?
  Pippo.FloatValue := d;
  ShowMessage('Valore 0,43 * 2 = '+floattostr(Pippo.FloatValue+Pippo.FloatValue));
  //No, non li ha
end;

procedure TForm1.Button2Click(Sender: TObject);
var d: double;
begin
  d := 100.43; // $EC51B81E851B5940  Valore 100,43 in double float
  //Pippo.FloatValue := d;
  Pippo.ByteArray[0] := $EC;
  Pippo.ByteArray[1] := $51;
  Pippo.ByteArray[2] := $B8;
  Pippo.ByteArray[3] := $1E;
  Pippo.ByteArray[4] := $85;
  Pippo.ByteArray[5] := $1B;
  Pippo.ByteArray[6] := $59;
  Pippo.ByteArray[7] := $40;
  ShowMessage('Valore 100,43 = '+floattostr(Pippo.FloatValue));
  //Sommiamo 9 al primo byte byte (per verificare le cifre significative e la rappresentatività)
  inc(Pippo.ByteArray[0], 9);
  ShowMessage('Incremento ultima cifra di 9 del Valore 100,43 = '+floattostr(Pippo.FloatValue));
  //Non cambia .... dobbiamo sommare 10 (1 di prima più 9) al primo byte byte (per verificare le cifre significative e la rappresentatività)
  inc(Pippo.ByteArray[0], 1);
  ShowMessage('Incremento di 10 nell''ultima cifra del Valore 100,43 = '+floattostr(Pippo.FloatValue));
  //Non cambia ancora.... dobbiamo sommare ulteriormente (non solo al primo byte ma dobbiamo combinare sia il primo che il secondo)

  //Quindi, riassumendo è cambiata la rappresentività del numero, con una piccola variazione (10) ora il valore non sembra cambiare, con il 0,43 si ......
end;

end.

Eseguite e leggete i commenti, vedrete come si comportano apparentemente i numeri ..... o meglio come cambia di significato la rappresentazione: pensate pure se svolgete la semplice addizione mostrata 1000 o 100000 volte nel corso del programma ....

Ciao
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

AlexLazarus

  • Jr. Member
  • **
  • Post: 91
  • Karma: +1/-0
Re:[RISOLTO] Da intero a virgola mobile a stringa
« Risposta #11 il: Gennaio 10, 2023, 06:51:24 am »
Incredibile, che dire? A quanto pare la verità matematica è ben nascosta nelle pieghe delle impostazioni di base.

Invece io ero rimasto a 2 + 2 = 4.  😐

 

Recenti

How To

Utenti
  • Utenti in totale: 785
  • Latest: gmax
Stats
  • Post in totale: 18771
  • Topic in totale: 2233
  • Online Today: 404
  • Online Ever: 900
  • (Gennaio 21, 2020, 08:17:49 pm)
Utenti Online
Users: 0
Guests: 402
Total: 402

Disclaimer:

Questo blog non rappresenta una testata giornalistica poiché viene aggiornato senza alcuna periodicità. Non può pertanto considerarsi un prodotto editoriale ai sensi della legge n. 62/2001.