Vamos dizer que tenho um valor de 3,4679 e quero 3,46, como posso truncar para duas casas decimais sem arredondar?
Eu tentei o seguinte, mas todos os três me deram 3,47:
void Main()
{
Console.Write(Math.Round(3.4679, 2,MidpointRounding.ToEven));
Console.Write(Math.Round(3.4679, 2,MidpointRounding.AwayFromZero));
Console.Write(Math.Round(3.4679, 2));
}
Isso retorna 3,46, mas parece sujo de alguma forma:
void Main()
{
Console.Write(Math.Round(3.46799999999 -.005 , 2));
}
Seria mais útil ter uma função completa para uso no mundo real de truncar um decimal em C #. Isso poderia ser convertido em um método de extensão decimal muito fácil se você quisesse:
Se você precisa de VB.NET, tente isto:
Em seguida, use-o assim:
ou
fonte
Use o operador de módulo:
resultado: 0,54
fonte
0.5400
... A resposta de D. Nesterov abaixo produziu o esperado0.54
.$"{0.54m:C}"
produz"$0.54"
e, sim,$"{0.5400m:C}"
produz"$0.54"
.Método universal e rápido (sem
Math.Pow()
/ multiplicação) paraSystem.Decimal
:fonte
Um problema com os outros exemplos é que eles multiplicam o valor de entrada antes de dividi-lo. Há um caso extremo aqui em que você pode estourar o decimal multiplicando primeiro, um caso extremo, mas algo que encontrei. É mais seguro lidar com a parte fracionária separadamente da seguinte maneira:
fonte
Vou deixar a solução para números decimais.
Algumas das soluções para decimais aqui estão sujeitas a estourar (se passarmos um número decimal muito grande e o método tentará multiplicá-lo).
A solução de Tim Lloyd é protegida contra estouro, mas não é muito rápida.
A solução a seguir é cerca de 2 vezes mais rápida e não tem um problema de estouro:
fonte
Truncate
método será agrupado com os nativos .net, proporcionando ao usuário uma experiência perfeita.Assert.AreEqual(1.1m, 1.12m.TruncateEx(1));
falha por causa disso. Se você especificar o arredondamento "normal" (AwayFromZero) na chamada Math.Round, entãoAssert.AreEqual(0m, 0m.TruncateEx(1));
falharáMidpointRounding.AwayFromZero
um código específico para lidar com o valor 0.Esta é uma questão antiga, mas muitos anwsers não funcionam bem ou transbordam para números grandes. Acho que a resposta de D. Nesterov é a melhor: robusta, simples e rápida. Eu só quero adicionar meus dois centavos. Eu brinquei com decimais e também verifiquei o código-fonte . Da
public Decimal (int lo, int mid, int hi, bool isNegative, byte scale)
documentação do construtor .Sabendo disso, minha primeira abordagem foi criar outro
decimal
cuja escala corresponda aos decimais que eu queria descartar, truncar e finalmente criar um decimal com a escala desejada.Este método não é mais rápido que o de D. Nesterov e é mais complexo, então brinquei um pouco mais. Meu palpite é que ter que criar um auxiliar
decimal
e recuperar os bits duas vezes o torna mais lento. Em minha segunda tentativa, eu mesmo manipulei os componentes retornados pelo método Decimal.GetBits (Decimal d) . A ideia é dividir os componentes em 10 vezes quantas forem necessárias e reduzir a escala. O código é baseado (fortemente) no método Decimal.InternalRoundFromZero (ref Decimal d, int decimalCount) .Não realizei testes de desempenho rigorosos, mas em um MacOS Sierra 10.12.6, processador Intel Core i3 de 3,06 GHz e direcionado para .NetCore 2.1 este método parece ser muito mais rápido do que o de D. Nesterov (não vou dar números desde , como já mencionei, meus testes não são rigorosos). Cabe a quem implementa isso avaliar se os ganhos de desempenho compensam ou não pela complexidade de código adicionada.
fonte
Isso funcionaria para você?
fonte
Daria o
((long)(3.4679 * 100)) / 100.0
que você quer?fonte
Aqui está um método de extensão:
fonte
Se você não se preocupa muito com o desempenho e seu resultado final pode ser uma string, a seguinte abordagem será resiliente a problemas de precisão flutuante:
fonte
Aqui está minha implementação da função TRUNC
fonte
que tal isso?
fonte
Além das soluções acima, há outra maneira de conseguir.
fonte
Em algumas condições, isso pode ser suficiente.
Eu tinha um valor decimal de SubCent = 0,009999999999999999999999999999M que tende a formatar para | SubCent: 0,010000 | via
string.Format("{0:N6}", SubCent );
e muitas outras opções de formatação.Minha exigência não era arredondar o valor do SubCent, mas também não registrar todos os dígitos.
O seguinte atendeu ao meu requisito:
Que retorna a string: | SubCent: 0,0099999 |
Para acomodar o valor que tem uma parte inteira, o seguinte é um começo.
Que retorna a string:
fonte
estou usando esta função para truncar valor após decimal em uma variável de string
fonte
Isso é o que eu fiz:
subtrair dois números inseridos sem arredondar para cima ou para baixo os decimais. porque as outras soluções não funcionam para mim. não sei se vai funcionar para os outros, só quero compartilhar isso :) Espero que funcione tho para aqueles que estão encontrando uma solução para um problema semelhante ao meu. obrigado
PS: eu sou um iniciante, fique à vontade para apontar algo sobre isso. : D isso é bom se você está realmente lidando com dinheiro, causa dos centavos certo? tem apenas 2 casas decimais e o arredondamento é um não não.
fonte
fonte
fonte
Na verdade, você quer 3,46 de 3,4679. Esta é apenas a representação de caracteres. Portanto, não há nada a ver com a função matemática. A função matemática não se destina a fazer este trabalho. Basta usar o seguinte código.
fonte
A respeito
fonte