Converta uma variável dupla para decimal

94

Como um elenco doublepara decimalqual é usado ao fazer o desenvolvimento da moeda. Para onde Mvai?

decimal dtot = (decimal)(doubleTotal);
flo
fonte

Respostas:

83

Você só usa Mpara um literal numérico, ao lançar é apenas:

decimal dtot = (decimal)doubleTotal;

Observe que um número de ponto flutuante não é adequado para manter um valor exato, portanto, se você primeiro somar os números e depois converter para, Decimalpoderá obter erros de arredondamento. Você pode querer converter os números em Decimalantes de adicioná-los, ou certifique-se de que os números não são números de ponto flutuante em primeiro lugar.

Guffa
fonte
como uma pergunta de acompanhamento, por que a conversão explícita é necessária? Eu tentei e recebo um erro que um duplo não pode ser convertido explicitamente em um decimal, mas um decimal não tem mais precisão? (ou seja, muito parecido com a conversão de um int para um duplo pode ser implícito.)
4
@Cortana: A precisão de um decimal é maior, mas o intervalo é menor. Um valor duplo pode estar fora do intervalo de um decimal. Consulte: stackoverflow.com/questions/7817866/…
Guffa
40

Você pode converter um duplo em um decimal assim, sem precisar do Msufixo literal:

double dbl = 1.2345D;
decimal dec = (decimal) dbl;

Você deve usar o Mao declarar um novo valor decimal literal:

decimal dec = 123.45M;

(Sem o M, 123,45 é tratado como um duplo e não será compilado.)

Chris Fulstow
fonte
28

use a classe de conversão padrão: Convert.ToDecimal(Double)

Timur Sadykov
fonte
1
Não porque lançará um OverflowException double vol_y = (double) Decimal.MaxValue + 10E + 28D; Console.WriteLine ("Convert.ToDecimal (vol_y) =" + Convert.ToDecimal (vol_y));
ToXinE 01 de
2
@ToXinE IMHO na maioria dos casos, um OverflowException é melhor do que uma criação silenciosa de dados errados
this.myself
16
Convert.ToDecimal(the double you are trying to convert);
Tom
fonte
2
Aprendi que a classe Convert é muito mais flexível e segura do que um elenco em C #.
Tom
3
"Seguro"? como em quando ele não pode lançar ele lança uma exceção em tempo de execução em vez de um erro do compilador? Fui mordido por isso tantas vezes que evito ativamente Converter ...
Peter Ritchie
8
O thread @PeterRitchie é um pouco antigo, mas isso deve ser dito: chamar o método Convert diretamente seria a abordagem mais apropriada. Talvez eu seja apenas um fanático por otimização, mas uma instrução a menos para resolver é um bônus (já que usar a sintaxe de cast explícita (Type) é apenas uma sobrecarga de operador que chama Convert).
Mike Johnson
1
@PeterRitchie: De uma perspectiva de design de linguagem, teria sido melhor exigir que um programador usasse um dos dois métodos de conversão em vez de permitir um typecast de doublepara decimal, dado que para um doublevalor como (1000000.0 / 3.0), seria em alguns casos deseja cortar a precisão "excessiva" produzindo 333333.333333333D, mas em outros casos, seria desejável retê-la, gerando 333333.333333333313931D. Em vez de simplesmente dizer "converter em decimal", o código deve especificar como essa conversão deve ser realizada.
supercat de
2
@supercat que realmente não parece relacionado ao meu primeiro comentário porque usar Convert.ToDecimal(double)é o mesmo que (decimal)doubleTotal, exceto se for doubleTotalalterado para um tipo diferente, você provavelmente evitará um erro de tempo de compilação e introduzirá um erro de tempo de execução mais difícil de encontrar porque um ToDecimal diferente override pode ser chamado. O operador de elenco é muito mais explícito ...
Peter Ritchie
1

Bem, esta é uma pergunta antiga e eu realmente usei algumas das respostas mostradas aqui. No entanto, em meu cenário específico, era possível que o doublevalor para o qual eu queria converter decimalfosse geralmente maior do que decimal.MaxValue. Então, em vez de lidar com exceções, escrevi este método de extensão:

    public static decimal ToDecimal(this double @double) => 
        @double > (double) decimal.MaxValue ? decimal.MaxValue : (decimal) @double;

A abordagem acima funciona se você não quiser se preocupar em lidar com exceções de estouro e se tal coisa acontecer, você deseja apenas manter o valor máximo possível (meu caso), mas estou ciente de que para muitos outros cenários este não seria o comportamento esperado e pode ser a manipulação de exceção será necessária.

Taquion
fonte
1
Isso falharia no seguinte caso double _double = (double) decimal.MaxValue; Eu sugeriria usar> = na comparação decimal público estático ToDecimal (este double _double) => _double> = (double) decimal.MaxValue? decimal.MaxValue: (decimal) _double;
Martin Eyles,