Como programador em C e programador em C #, uma das coisas que eu não gosto no C # é como são as funções matemáticas detalhadas. Toda vez que você precisaria usar uma função Sin, cosseno ou potência, por exemplo, teria que preceder a classe estática Math. Isso leva a um código muito longo quando a própria equação é bastante simples. O problema fica ainda pior se você precisar digitar tipos de dados. Como resultado, na minha opinião, a legibilidade sofre. Por exemplo:
double x = -Math.Cos(X) * Math.Sin(Z) + Math.Sin(X) * Math.Sin(Y) * Math.Cos(Z);
Ao contrário de simplesmente
double x = -cos(X) * sin(Z) + sin(X) * sin(Y) * cos(Z);
Este também é o caso em outros idiomas como Java.
Não tenho certeza se essa pergunta realmente tem uma solução, mas gostaria de saber se existem truques que os programadores de C # ou Java usam para melhorar a legibilidade do código Math. Percebo, no entanto, que C # / Java / etc. não são linguagens orientadas à matemática como MATLAB ou similar, por isso faz sentido. Mas, ocasionalmente, ainda é necessário escrever código matemático e será ótimo se você puder torná-lo mais legível.
fonte
using System.Math; … double x = -Cos(X) * Sin(Z) + Sin(X) * Sin(Y) * Cos(Z);
.Respostas:
Você pode definir funções locais que chamam as funções estáticas globais. Esperançosamente, o compilador alinhará os wrappers e, em seguida, o compilador JIT produzirá um código de montagem rígido para as operações reais. Por exemplo:
Você também pode criar funções que agrupam operações matemáticas comuns em operações únicas. Isso minimizaria o número de instâncias em que funções gostam
sin
ecos
aparecem no seu código, tornando menos perceptível a dificuldade de chamar as funções estáticas globais. Por exemplo:Você está trabalhando no nível de pontos e rotações, e as funções trigonométricas subjacentes são ocultadas.
fonte
No Java, existem muitas ferramentas disponíveis para tornar certas coisas menos detalhadas, você só precisa estar ciente delas. Um que é útil nesse caso é o da
static
importação ( página do tutorial , wikipedia ).Nesse caso,
corre muito bem ( ideone ). É um pouco pesado fazer uma importação estática de toda a classe Math, mas se você estiver fazendo muita matemática, pode ser necessário.
A importação estática permite importar um campo ou método estático para o espaço de nomes dessa classe e invocá-lo sem exigir o nome do pacote. Você costuma encontrar isso nos casos de teste do Junit, onde
import static org.junit.Assert.*;
é possível obter todas as declarações disponíveis.fonte
public interface Constants { final static public double PI = 3.14; }
e,public class Foo implements Constants
em todas as classes, para obter acesso às constantes na interface. Isso fez uma grande bagunça. Portanto, com o 1.5, a importação estática foi adicionada para permitir a inserção de constantes e funções estáticas específicas sem a necessidade de implementar uma interface.import static java.lang.Math.cos;
Com o C # 6.0, você pode usar o recurso de importação estática.
Seu código pode ser:
Consulte: Static Using Statements (Visualização de idioma do AC # 6.0)
EDIT: desde o Visual Studio 2015, o CTP lançado em janeiro de 2015, a importação estática requer uma palavra-chave explícita
static
. gostar:fonte
Além das outras boas respostas aqui, também posso recomendar uma DSL para situações com complexidade matemática substancial (não casos de uso médios, mas talvez alguns projetos financeiros ou acadêmicos).
Com uma ferramenta de geração de DSL como o Xtext , você pode definir sua própria gramática matemática simplificada, que por sua vez pode gerar uma classe contendo a representação Java (ou qualquer outra linguagem) de suas fórmulas.
Expressão DSL:
Saída gerada:
Em um exemplo tão simples, os benefícios da criação da gramática e do plug-in do Eclipse não valeriam a pena, mas para projetos mais complicados, poderia render grandes benefícios, especialmente se o DSL permitisse que pessoas de negócios ou pesquisadores acadêmicos mantivessem documentos formais de maneira confortável. idioma e tenha certeza de que o trabalho deles foi traduzido com precisão para o idioma de implementação do projeto.
fonte
Em C #, você poderia usar métodos de extensão.
A seguir, você lê bem quando se acostuma à notação "postfix":
Infelizmente, a precedência do operador torna as coisas um pouco mais feias quando se lida com números negativos aqui. Se você deseja calcular em
Math.Cos(-X)
vez de-Math.Cos(X)
, precisará colocar o número entre parênteses:fonte
x.Sin()
precisaria de algum ajuste, mas eu abuso os métodos de extensão e essa seria, pessoalmente, minha primeira inclinação.C #: Uma variação da resposta de Randall Cook , que eu gosto porque mantém a "aparência" matemática do código mais do que os métodos de extensão, é usar um wrapper, mas usar referências de função para as chamadas em vez de envolvê-las. Pessoalmente, acho que faz o código parecer mais limpo, mas basicamente está fazendo a mesma coisa.
Eu encerrei um pequeno programa de teste do LINQPad, incluindo as funções agrupadas de Randall, minhas referências de função e as chamadas diretas.
As chamadas referenciadas à função geralmente levam o mesmo tempo que as chamadas diretas. As funções agrupadas são consistentemente mais lentas - embora não em grande quantidade.
Aqui está o código:
Resultados:
fonte
Use Scala! Você pode definir operadores simbólicos e não precisa de parênteses para seus métodos. Isso facilita muito a interpretação da matemática .
Por exemplo, o mesmo cálculo no Scala e Java pode ser algo como:
Isso aumenta muito rapidamente.
fonte