Perché Math.Floor (Double) restituisce un valore di tipo Double?


103

Devo ottenere il valore intero sul lato sinistro da un decimale o un doppio. Ad esempio: devo ottenere il valore 4 da 4.6. Ho provato a utilizzare la funzione Math.Floor ma restituisce un valore doppio, ad esempio: restituisce 4.0 da 4.6. La documentazione MSDN dice che restituisce un valore intero. Mi manca qualcosa qui? O c'è un modo diverso per ottenere ciò che cerco?


2
La documentazione MSDN dice che restituisce un valore intero . La documentazione di MSDN indica che Math.Floor restituisce System.Double, non integer.
banda larga

Un valore intero è effettivamente necessario, ma non significa che possa essere memorizzato in un "int" o "long". Un "double" memorizza con successo tutti i valori interi in un intervallo molto più ampio del solo "int" Nota che alcuni valori interi possono essere arrotondati quando la parte mantissa non ha abbastanza bit per memorizzare tutte le cifre del valore intero, quando il suo esponente in base 2 va sopra 52: questo arrotondamento dei valori interi in "double" può verificarsi per interi sopra 2 ^ 52 o sotto -2 ^ 52 ma il risultato sarà comunque il numero intero rappresentabile più vicino; se usi "(long) Floor (x)", la conversione potrebbe essere ampiamente sbagliata.
verdy_p

Si noti tuttavia che l'intervallo valido di valori interi che possono essere rappresentati in un "doppio" è estremamente ampio, con valori assoluti fino a: (1 + (1 - 2 ^ −52)) × 2 ^ 1023 ≈ 1.7976931348623157E308; è molto più di 2 ^ 63-1 con "lungo". Tuttavia la gamma di interi che possono essere memorizzati distintamente è più ristretta, perché un "double" ha solo 52 bit per la mantissa (più 1 bit implicito per il bit più significativo, non memorizzato), il che significa che "double" può memorizzare solo interi esattamente o solo quando il loro valore assoluto è inferiore a 2 ^ 53.
verdy_p

Sfortunatamente, Math.Floor () non restituisce internamente un tipo di variabile "Number" utilizzando "Long" se possibile, o "Double" altrimenti solo per interi grandi arrotondati. E la libreria matematica standard non gestisce questo tipo di numero variabile unificato. Esistono altre librerie matematiche che implementano un tipo di numero unificato, inclusi numeri interi lunghi, doppi o grandi codificati in formato decimale o binario compressi senza perdita di intervallo o precisione supportati.
verdy_p

Risposte:


146

La gamma di doubleè molto più ampia della gamma di into long. Considera questo codice:

double d = 100000000000000000000d;
long x = Math.Floor(d); // Invalid in reality

Il numero intero è al di fuori dell'intervallo di long, quindi cosa ti aspetti che accada?

In genere sai che il valore sarà effettivamente compreso nell'intervallo into long, quindi lo lanci:

double d = 1000.1234d;
int x = (int) Math.Floor(d);

ma l'onere di quel cast è sullo sviluppatore, non su Math.Floorse stesso. Sarebbe stato inutilmente restrittivo farlo fallire con un'eccezione per tutti i valori al di fuori dell'intervallo di long.


2
Floor restituisce la rappresentazione intera di double e restituisce double per i calcoli scientifici, questa risposta non è corretta perché double ha 64 bit e long ha anche 64 bit, ma double non può memorizzare le cifre esatte dei bit significativi inferiori anche se può essere memorizzato correttamente in lungo.
Akash Kava

1
@ Jon: come mai non hai soppesato il dibattito che imperversa su come rendere negativo un numero positivo in C # ? :
stackoverflow.com/questions/1348080/…

3
@ Jon: prenditi il ​​tuo tempo. Si scopre che la comunità ha scoperto che moltiplicando un numero positivo per -1 lo renderà negativo. Tutto va bene su StackOverflow.
MusiGenesis

1
@javapowered: No, (int) 15.0 non è 0. Qualcos'altro è andato storto, ma non possiamo dire cosa da solo. Crea un programma breve ma completo che lo dimostri, quindi fai una domanda. Sospetto che troverai difficile riprodurti ...
Jon Skeet,

1
@MusiGenesis: <code> (int) IGNORE_RATIO * Volume </code> è calcolato come <code> (int) 0.15 * Volume </code>, ma il typecast si applica solo al rapporto, non al risultato del prodotto, e ottieni <code> 0 * Volume </code> cioè zero! Usa <code> (int) (IGNORE_RATIO * Volume) </code> invece per risolvere il TUO bug.
verdy_p

11

Secondo MSDN, Math.Floor (double) restituisce un double: http://msdn.microsoft.com/en-us/library/e0b5f0xb.aspx

Se lo vuoi come int:

int result = (int)Math.Floor(yourVariable);

Posso vedere come l'articolo MSDN possa essere fuorviante, avrebbero dovuto specificare che mentre il risultato è un "intero" (in questo caso significa numero intero) è ancora di TIPO Doppio


Grazie per la risposta. In realtà stavo guardando questo articolo: msdn.microsoft.com/en-us/library/e0b5f0xb.aspx Ma comunque, proverò il tuo suggerimento. Grazie.

È vero, in alto si dice "restituisce un numero intero" ma il tipo è specificato sotto: public static double Floor (double d)
Neil N

3
intero! = int( risposte.com/integer ) - gli interi possono essere memorizzati in Double(vedi la risposta di Jon), e ci sono un numero infinito di numeri interi che non possono essere memorizzati in un file int.
Shog9

Shog, non ho detto che non potevano. Quello che ho detto è stato "è ancora di TYPE Double"
Neil N

1
@ Neil: giusto - volevo solo sottolineare la differenza tra "intero" (nome di un set) e int(nome di un tipo).
Shog9

4

Se hai solo bisogno della parte intera di un numero, esegui il cast del numero in un file int. Questo troncerà il numero al punto decimale.

double myDouble = 4.6;
int myInteger = (int)myDouble;

2
È importante notare che il casting intsi comporta diversamente da Floor, per i numeri negativi. Floortroncerà sempre al numero più negativo, mentre il cast su inttroncerà verso 0.
Magnus


0

Il pavimento lo lascia come un doppio in modo da poter fare più doppi calcoli con esso. Se lo vuoi come int, esegui il cast del risultato di floor come int. Non lanciare il double originale come int perché le regole per floor sono diverse (IIRC) per i numeri negativi.


0
Convert.ToInt32(Math.Floor(Convert.ToDouble(value)))

Questo vi darà il valore esatto ciò che si vuole, come se si prende 4.6restituisce 4come output.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.