Mi sono imbattuto in una diatriba matematica, irrisolta e irrisolvibile probabilmente.
Per adesso ho imposto la mia idea, ossia il calcolo in PASCAL (potevo farlo essendo il capo progetto) e la questione operativa è chiusa ... ma non è per niente risolta la problematica pratica.
Eseguendo una operazione matematica in pascal, tramite interi e resti (div e mod), i risultati delle operazioni sono a mio avviso chiare e non ho mai avuto dubbi, sino a quando non mi sono interfacciato con dei moduli in python (e mi dicono che anche con moduli google si ottengo risultati identici al python) in cui i risultati differiscono dal Pascal (ma anche dal C)
Esempio:
//Questa è equivalente per entrambe
var i, j: INT64;
begin
i := 9;
j := 5;
ShowMessage(IntToString(i div j)) // ==> 1
//Python: (9 // 5) ==> 1
end;
//Qui iniziano i dolori !!!
var i, j: INT64;
begin
i := -9;
j := 5;
ShowMessage(IntToString(i div j)) // ==> -1
//Python: (-9 // 5) ==> -2 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
end;
Per il modulo vale ovviamente la stessa differenziazione (quindi i risultati sono differenti in base al fatto che i risultati siano negativi o positivi).
Ciò perchè le operazioni vengono effettuate sempre in float per alcuni linguaggi e i risultati vengono "arrotondati" per difetto o per eccesso (floor o ceil) a seconda delle convenzioni del linguaggio.
Avete informazioni su ciò? Ovvero avete notizia di come funzioni in altri linguaggi ?
Ulteriormente, secondo voi è più corretto una / altra o entrambe (ogni linguaggio si gestisce a modo proprio) ?
La mia opinione è che non ci dovrebbero essere dubbi su queste cose (e io non ce ne ho, sono convinto della mia idea magari antiquata), invece vedo che siamo ancora in alto mare ...
N.B.: lasciando perdere l'arrotondamento, il problema principale e che i risultati e le successive operazioni possono essere notevolmente dissimili tra due procedure effettuate con linguaggi differenti, ad esempio nel caso si debbano usare per vari motivi moduli diversi.
In effetti il risultato è emblematico.
L'operatore // in python (come si può vedere anche nel link sotto)
https://www.w3schools.com/python/trypython.asp?filename=demo_oper_floordiv (https://www.w3schools.com/python/trypython.asp?filename=demo_oper_floordiv)
in realtà arrotonda il risultato all'intero più vicino.
Bene, però qualcosa non torna.
9/5, come dice bonmario fa 1.8
però mentre è corretto a questo punto che -9/5 dia come risultato -2, è errato che 9/5 dia come risultato 1! Dovrebbe dare 2.
Riguardo l'operatore div, secondo me il pascal risponde correttamente.
Ho voluto simulare quello che fa il python con Round (la Round del pascal arrotonda all'intero più vicino).
Infatti eseguendo il codice sotto, vedrete che i risultati sono esatti:
- Round(9/5) = 2
- Round(-9/5) = -2
program Hello;
var i, j: INT64;
begin
writeln ('a)', 9 div 5);
writeln ('b)', -9 div 5);
writeln ('c)', Round(9 / 5));
writeln ('d)', Round(-9 / 5));
end.
Direi che è chiaro che bisogna sapere che operazione si vuole svolgere, ma il python secondo me in questo caso non da risultati corretti.
Edit:
in effetti credo di aver preso una stecca ::)
l'operatore // del python "rounds the result down to the nearest whole number"
che in effetti significa che arrotonda all'interno minore
quindi l'intero minore di 1.8 è 1
mentre l'intero minore di -1.8 è -2
l'inghippo è che non si tratta solo di una divisione ma di una divisione con un arrotondamento all'intero minore
che comunque sono due operazioni che in effetti vengono svolte correttamente
NB:
la Round del pascal arrotonda all'interno più vicino
Per chi vuole, questo è il codice per fare con processori INTEL X64 in tutti i sistemi operativi teoricamente il calcolo tra numeri interi in modo "informatico" (ciò che fà il Pascal con il DIV e il MOD.
Poi farò anche i vari overload per i tipi e per x86.
{$IFDEF CPUX64}
/// <summary> Esegue una divisione per interi fornendo come risultato quoziente e resto </summary>
/// <remarks> Esegue il calcolo da "informatico" stile tutto chiaro !!! </remarks>
function DivandMod(Dividendo: int64; Divisore: int64; var Resto: int64): int64; register;
begin
{$ASMMODE intel}
asm
//Dividendo, in RCX
//Divisore, in RDX
//Resto, memoria puntata da R8
//Risultato (quoziente) in RAX
mov RAX, RCX
mov RCX, RDX
CQO
//idiv esegue la divisione intera e riporta il quoziente in RAX e in RDX il resto
idiv RCX
//SONO EQUIVALENTI LE DUE SUCCESSIVE IN DELPHI, IN LAZARUS NO !!!
mov QWORD PTR [R8], RDX
//mov QWORD PTR [Resto], RDX //SOLO X DELPHI
end;
end;
{$ENDIF}
procedure TForm1.Button1Click(Sender: TObject);
var quoziente: integer;
resto: int64;
Dividendo: int64;
Divisore: int64;
begin
Dividendo := 9;
Divisore := -5;
resto := 15;
quoziente := DivandMod(Dividendo, Divisore, resto);
ShowMessage('Quoziente= '+quoziente.ToString+' Resto= '+resto.ToString);
end;[/code