Come si fa a codice per determinare il logaritmo di un valore in Ada?
Domanda
Utilizzando Ada (GNAT): Ho bisogno di determinare la potenza di dieci per un dato valore. L'approccio più ovvio è quello di utilizzare un logaritmo; ma che non riesce a compilare.
with Ada.Numerics.Generic_Elementary_Functions;
procedure F(Value : in Float) is
The_Log : Integer := 0;
begin
The_Log := Integer(Log(Value, 10));
G(Value, The_Log);
end;
errore:
- utilities.adb: 495: 26: "Log" non è visibile
- utilities.adb: 495: 26: dichiarazione non visibile a-ngelfu.ads:24, esempio alla riga 482
- utilities.adb: 495: 26: dichiarazione non visibile a-ngelfu.ads:23, esempio alla riga 482
Allora tento di fare riferimento al pacchetto, ma che fallisce anche:
with Ada.Numerics.Generic_Elementary_Functions;
procedure F(Value : in Float) is
The_Log : Integer := 0;
package Float_Functions is new Ada.Numerics.Generic_Elementary_Functions (Float);
begin
The_Log := Integer(Float_Functions.Log(Value, 10));
G(Value, The_Log);
end;
errore:
- utilities.adb: 495: 41: nessun interpretazioni candidati corrispondono ai valori effettivi:
- utilities.adb: 495: 41: troppi argomenti nella chiamata a "Log"
- utilities.adb: 495: 53: tipo previsto "Standard.Float"
- utilities.adb: 495: 53: trovato tipo intero universale ==> in chiamata a "Log" a a-ngelfu.ads:24, esempio alla linea 482
Soluzione
Non so se è stato risolto già o no, ma qui è la risposta.
Prima di tutto, per come la vedo si sta passando Float
quando si crea un'istanza della versione generica che si può usare quello non generica, invece.
Se si decide di utilizzare la versione generica che dovete fare è il secondo modo che hai fatto, è necessario istanziare il pacchetto prima di utilizzare le sue funzioni.
Guardando a-ngelfu.ads è possibile vedere il prototipo reale della funzione desiderata (c'è un'altra funzione per il logaritmo naturale con appena 1 parametro):
function Log(X, Base : Float_Type'Base) return Float_Type'Base;
Si può vedere lì che la base ha bisogno di essere in un tipo float troppo. Il codice corretto per la versione generica potrebbe essere:
with Ada.Numerics.Generic_Elementary_Functions;
procedure F(Value : in Float) is
-- Instantiate the package:
package Float_Functions is new Ada.Numerics.Generic_Elementary_Functions (Float);
-- The logarithm:
The_Log : Integer := 0;
begin
The_Log := Integer(Float_Functions.Log(Value, 10.0));
G(Value, The_Log);
end;
L'uno non generico sarebbe esattamente lo stesso:
with Ada.Numerics.Elementary_Functions;
procedure F(Value : in Float) is
-- The logarithm:
The_Log : Integer := 0;
begin
The_Log := Integer(Ada.Numerics.Elementary_Functions.Log(Value, 10.0));
G(Value, The_Log);
end;
Altri suggerimenti
Xandy è giusto. La sua soluzione ha funzionato.
Tuttavia essendo Ada c'erano due eccezioni per tutelarsi dai ...
- Valore <0.0
- Value = 0.0
Senza guardie questa funzione in quanto è causa eccezioni da generare. E ricordate The_Log come restituito può essere <0, 0, e> 0.
with Ada.Numerics.Elementary_Functions;
procedure F(Value : in Float) is
-- The logarithm:
The_Log : Integer := 0;
begin
if Value /= 0.0 then
The_Log := Integer(
Ada.Numerics.Elementary_Functions.Log(abs Value, 10.0));
end if;
G(Value, The_Log);
end;