Pergunta

Essas linhas em C#

decimal a = 2m;
decimal b = 2.0m;
decimal c = 2.00000000m;
decimal d = 2.000000000000000000000000000m;

Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
Console.WriteLine(d);

Gera esta saída:

2
2.0
2.00000000
2.000000000000000000000000000

Então posso ver que criar uma variável decimal a partir de um literal me permite controlar a precisão.

  • Posso ajustar a precisão das variáveis ​​decimais sem usar literais?
  • Como posso criar b a partir de a?Como posso criar b a partir de c?
Foi útil?

Solução

A preservação de zeros à direita como essa foi introduzida no .NET 1.1 para uma conformidade mais estrita com a especificação ECMA CLI.

Há algumas informações sobre isso no MSDN, por ex. aqui.

Você pode ajustar a precisão da seguinte forma:

  • Math.Round (ou teto, piso etc) para diminuir a precisão (b de c)

  • Multiplique por 1.000...(com o número de casas decimais desejadas) para aumentar a precisão - por exemplo.multiplique por 1,0M para obter b de a.

Outras dicas

Você está apenas vendo representações diferentes dos mesmos dados.A precisão de um decimal será dimensionado para ser tão grande quanto necessário (dentro do razoável).

De System.Decimal:

Um número decimal é um ponto flutuante valor que consiste em um sinal, um valor numérico onde cada dígito no o valor varia de 0 a 9, e Um fator de escala que indica a posição de um ponto decimal flutuante que separa as partes integrais e fracionárias do valor numérico.

A representação binária de um decimal valor consiste em um sinal de 1 bit, um Número inteiro de 96 bits e um dimensionamento fator usado para dividir o 96-bit inteiro e especifique qual parte dele é uma fração decimal.O dimensionamento fator é implicitamente o número 10, elevado a um expoente que varia de 0 até 28.Portanto, o binário a representação de um valor decimal é da forma, ((-296 para 296) / 10(0 a 28)), onde -296-1 é igual a Valor mínimo e 296-1 é igual a MaxValue.

O fator de dimensionamento também preserva qualquer zeros à direita em um número decimal.Os zeros à direita não afetam o valor de um número decimal em operações aritméticas ou de comparação.No entanto, zeros à direita podem ser revelado pelo método ToString se um a cadeia de caracteres de formato apropriado é aplicada.

Descobri que poderia "alterar" a escala multiplicando ou dividindo por um sofisticado 1.

decimal a = 2m;
decimal c = 2.00000000m;
decimal PreciseOne = 1.000000000000000000000000000000m;
  //add maximum trailing zeros to a
decimal x = a * PreciseOne;
  //remove all trailing zeros from c
decimal y = c / PreciseOne;

Posso fabricar um 1 suficientemente preciso para alterar os fatores de escala por tamanhos conhecidos.

decimal scaleFactorBase = 1.0m;
decimal scaleFactor = 1m;
int scaleFactorSize = 3;

for (int i = 0; i < scaleFactorSize; i++)
{
  scaleFactor *= scaleFactorBase;
}

decimal z = a * scaleFactor;

É tentador confundir decimal no SQL Server com decimal na rede;eles são bem diferentes.

Um servidor SQL decimal é um número de ponto fixo cuja precisão e escala são fixas quando a coluna ou variável é definida.

UMA REDE decimal é um número de ponto flutuante como float e double (a diferença é que decimal preserva com precisão os dígitos decimais, enquanto float e double preservar com precisão os dígitos binários).Tentando controlar a precisão de um .NET decimal é inútil, pois todos os cálculos produzirão os mesmos resultados, independentemente da presença ou ausência de zeros de preenchimento.

A questão é: você realmente precisa da precisão armazenado no decimal, em vez de apenas exibir o decimal com a precisão necessária.A maioria dos aplicativos sabe internamente o quão precisos eles desejam ser e exibem esse nível de precisão.Por exemplo, mesmo que um usuário insira uma fatura de 100 em um pacote de contas, ela ainda será impressa como 100,00 usando algo como val.ToString("n2").

Como posso criar b a partir de a?Como posso criar b a partir de c?

c para b é possível.

Console.WriteLine(Math.Round(2.00000000m, 1)) 

produz 2,0

a para b é complicado porque o conceito de introdução de precisão é um pouco estranho à matemática.

Acho que um hack horrível pode ser uma viagem de ida e volta.

decimal b = Decimal.Parse(a.ToString("#.0"));
Console.WriteLine(b);

produz 2,0

Isso removerá todos os zeros à direita do decimal e então você poderá simplesmente usar ToString().

public static class DecimalExtensions
{
    public static Decimal Normalize(this Decimal value)
    {
        return value / 1.000000000000000000000000000000000m;
    }
}

Ou, alternativamente, se você quiser um número exato de zeros à direita, digamos 5, primeiro Normalize() e depois multiplique por 1,00000m.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top