Pergunta

Hugs> 94535^445
1376320882321377050696053887661515621104890164005282153069726424773999801846841903244827702943487982707454966009456016735041878000604143500908532887464920380605164932112687039059526672109818924234920844448231612532570718657160234177285377733830104834041049076609912488237219608445995072867798430614935403219495883835042862802917980856774134757390782052200512932375660858045003581611863121089979673784484701791210379500218604466721285456487387736825167702127154268533859979529612671925052419513844416493584817268143587955662039327860394141299238613042312035808541735213479394437496215520277526351425482512084759462579494878772787079101513841720202004639843443083454387175700954018825292148776647553122504118229978165851660083576570848983047255050145168802863168613110619584686348869690774233051669081248424584219383477237544209892290799448207462345346336076966775224683516220960618177284844330167142846351091001423033864986042919757795382577032341453971393897073354841924116635150129850119992031076354249371062307034564093077675129303383786693131843907104175619570678630497198824622804914508555467550904967368926176118094672479099827962889569753303773699017596074205893197641101210911874606040804983166177455705972192827752532495287749766682029353154226049380290040508900715169403153139668217790502306177709467234413947747673881158973344492079455405942662489751581189327200960698310350121179918845099840977270519116578719881752429190273998774113278822810866144521416958558406602325070095207349450759264393913367193083149679216066539911941983836313340998945139132421885688290888674594474605510238217590823316979504437667252929278291853368754482552573193289277120902144178425726693671235675042499401282016643202758246845332593475338220708351934511933096882598943512036679145593929114103343255708217768511665236173107020739195152050863630870948954052925049746246549772984384435109578859863612603574306739909728739428192798727373799081111333186135697868385292787575475482883660605162944306327057220313320376280182432763977906971557137715710757099478269250731209785404487629107297262798803645379809868663503452656912571816192881412782623078761411808958183665272686617730596943579533808499348879195167683064937591552734375

Por que Haskell consegue calcular um número tão grande e outras linguagens, como Java, não conseguem (tão facilmente)?

Foi útil?

Solução

Java tem o Biginteger classe.

Poderia ter construído essa instalação no idioma, mas (como muitos idiomas) tende a tornar os recursos primitivos mapearem de perto as coisas que são suportadas pela CPU.

Haskell, por outro lado, enfatiza a expressividade no estilo de notação matemática, onde as considerações de "desempenho" são amplamente irrelevantes.

Outras dicas

É um diferença na filosofia do design:

  • Os designers de Haskell queriam ter certeza de que os usuários não ficariam surpresos com a falha aparentemente arbitrária de uma computação inteira que precisa de mais de 32 bits.

  • Os designers da Java queriam ter certeza de que os usuários não ficariam surpresos com a degradação de desempenho aparentemente arbitrária causada por muitos cálculos sobre os números inteiros que precisam de mais de 32 bits.

Em cada idioma, você precisa fazer algo especial para obter o outro tipo de número inteiro.

Há uma longa e honrosa história de idiomas que apoiam arbitrariamente grandes números inteiros por padrão. Dois dos meus favoritos são Ícone e Conversa fiada, que têm mais de 25 anos.

Literais numéricos em Haskell estão sobrecarregados para que possam representar vários tipos de concreto (como Int, Integer, Float ou até MyOwnNumber).

Você pode escolher manualmente um tipo específico, fornecendo informações de tipo, como assim:

x = 4 :: Int
y = 4 :: Integer
z = 4 :: Float

Esses três valores têm diferentes tipos e operações executados neles se comportarão de maneira diferente.

O tamanho exato de um Int é dependente da implementação, mas pode ser algo como 28 bits, esse tipo se comporta como uma primitiva java int, por exemplo, vai transbordar.

Um Integer é um tipo que pode conter números inteiros de precisão arbitrária, como o Java Biginteger.

E a Float é como um java float, usando aritmética do ponto flutuante.

Assim como literais numéricos, muitos operadores também estão sobrecarregados (usando Tipo classes) e, portanto, pode ser usado com os diferentes tipos. Então o + O operador pode trabalhar com ambos Intareia Floats.

No seu caso, como você não forneceu nenhuma informação de tipo, o intérprete não será Integer modelo. Isso significa que para o ^ operador, também escolherá o Integer instância. Permitindo cálculos inteiros de precisão arbitrária.

Java tem a noção de “Tipos de dados primitivos” (que são os tipos que o processador suporta) e são diferentes de todas as outras classes.

Em Haskell, Int é um tipo como todos os outros tipos e, portanto, foi facilmente tornado membro do Num e Integral classes de tipo usadas em (^) ("(^) :: (Num a, Integral b) => a -> b -> a").Outro membro dessas classes de tipo é Integer, que suporta números inteiros de todos os tamanhos (desde que você tenha memória suficiente para seus dígitos).

Em Java, você pode usar muitas bibliotecas de "Grandes Números", mas as operações para elas não usarão os operadores infixos com os quais você está acostumado, porque eles são apenas para "Tipos Primitivos" em Java.

A resposta curta e básica é que eles implementam os números inteiros padrão diferentes. Em Java, um INT padrão é de 32 bits. Assinado, isso lhe dá uma variedade de −2,147,483,648 para +2,147,483,647.

Dito isto, Java tem bignum Aulas também. Se você os usar, também ganhará a capacidade de usar números arbitrariamente grandes.

Como já mencionado, se você tiver palavras de 32 bits e usar o intervalo completo, obterá -2^31 a 2^31-1 usando complemento de dois.

Ao reservar alguns bits da palavra, esses bits podem ser usados ​​para transportar informações de tipo para o valor.Ou seja, os valores “conhecem” seu próprio tipo em tempo de execução.Os bits restantes são usados ​​para transportar os dados do valor.

Valores inteiros que cabem nesses bits restantes podem ser armazenados diretamente na palavra.Esses números inteiros são normalmente chamados de 'fixnums'.Se eles não couberem, os bits de tipo da palavra indicam que é 'bigint' e os bits restantes são usados ​​para armazenar um ponteiro de memória no heap onde o valor bigint está armazenado.

O compilador precisa traduzir suas expressões aritméticas em vários caminhos de código que abrangem combinações de tipos permitidas para os operandos.Exemplo de adição:

  • número fixo + número fixo
  • bigint + fixnum
  • fixnum + bigint
  • bigint + bigint

Muitas otimizações em compiladores para essas linguagens se concentram em evitar sobrecarga nas verificações de tipo de tempo de execução necessárias para fazer isso funcionar.Freqüentemente, também há maneiras de informar explicitamente ao compilador que o rebaixamento automático de fixnum para bignum é indesejável e, em vez disso, deseja-se o comportamento de overflow de números inteiros de 32 bits.Isto pode ser muito importante para implementar algoritmos de criptografia de forma eficiente.

É uma questão de como codificar números. A maneira tradicional de fazer isso é codificar números com um determinado número de bits, onde você não pode ter uma precisão infinita. Haskell aparentemente faz isso com um número variável de bits para um número que também é bom, mas geralmente significa que toda a matemática é feita no software, pois a aceleração de hardware geralmente está disponível apenas para precisão finita.

Você pode usar o BIGINTEGER para fazer a mesma coisa. Haskell é uma linguagem funcional que é mais concisa que Java.

Uma razão pela qual temos tantos idiomas é que diferentes idiomas são melhores em tarefas diferentes, pois foram projetadas com suposições diferentes. A maioria dos idiomas funcionais é mais simples com as funções matemáticas, mas tende a lutar com outros casos de uso, por exemplo, Haskell é improvável que seja uma boa escolha para escrever uma GUI.

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