Ответ 1
Вам нужно использовать какую-то форму BigInteger.
Попробуйте (apply *' (range 1 101))
.
(см. http://dev.clojure.org/display/doc/Documentation+for+1.3+Numerics - очевидно, что это автоматически способствует переполнению?)
Кажется, это происходит все время. Например:
(apply * (range 1 101))
дает ошибку
ArithmeticException integer overflow clojure.lang.Numbers.throwIntOverflow (Numbers.java:1374)
Пока в Ruby 1.9.2 (концептуально) эквивалентный код,
(1..100).reduce(:*)
дает желаемый результат
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
Очевидно, что два языка сильно различаются под капотом, но похоже, что оба они могут справиться с этим вычислением без проблем. Я здесь что-то не так? Или я неправильно понимаю?
Вам нужно использовать какую-то форму BigInteger.
Попробуйте (apply *' (range 1 101))
.
(см. http://dev.clojure.org/display/doc/Documentation+for+1.3+Numerics - очевидно, что это автоматически способствует переполнению?)
Ruby имеет автоматическое продвижение вычислений, меняя его на большее число биттипов, когда результат переполняет его тип. Из соображений производительности вычисления с Clojure 1.3 вверх не будут автоматически повышаться, и вам нужно учитывать, может ли вычисление переполняться, или использовать одну из автоматических математических функций (+'
, -'
, *'
, /'
), если производительность не будет проблемой.
Из Clojure 1.3 вы должны явно указывать Integer (или Long) на BigInt, иначе при слишком большом числе будет ошибка "Переполнение целых чисел ArithmeticException".
Есть три решения, пожалуйста, выберите тот, который вы предпочитаете:
используйте одну из автоматических математических функций: +', -', *', /', inc', dec'
Пример: (apply *' (range 1 101))
используйте функцию заливки типа BigInt
Пример: (apply * (range (bigint 1) 101))
изменить числовой литерал BigInt
пример: (apply * (range 1N 101))
Наткнулся на ту же ситуацию. Для меня использование "1.0" вместо "1" сделало трюк.
(apply * (range 1.0 1000))
Поскольку документировано, существует разница между поплавками и десятичными знаками.
Я не знаю Clojure, но похоже, что он использует 32-битные или 64-разрядные целые числа для вычисления. 32-разрядные целые числа со знаком имеют максимальное значение 2^31 - 1
(бит более 2 * 10 ^ 9). 64-битные целые числа имеют максимальное значение 2^64 - 1
(бит более 4 * 10 ^ 18). Значение, которое вы получили от Ruby, намного выше.
Очевидно, Ruby использует некоторое другое представление числа под капотом.
в 1.3.0
(применить * (диапазон 1N 101N)); clojure.lang.BigInt
(применить * (диапазон 1M 101M)); java.math.BigDecimal