Тип номера as3 - проблемы логики с большими числами - PullRequest
2 голосов
/ 27 сентября 2011

Мне любопытно узнать о проблеме, обнаруженной в нашей команде с очень большим числом:

var n:Number = 64336512942563914;
trace(n < Number.MAX_VALUE); // true
trace(n); // 64336512942563910

var a1:Number = n +4;
var a2:Number = a1 - n;
trace(a2); // 8  Expect to see 4
trace(n + 4 - n); // 8

var a3:Number = parseInt("64336512942563914");
trace(a3); // 64336512942563920

n++;
trace(n); //64336512942563910
trace(64336512942563914 == 64336512942563910); // true

Что здесь происходит?

Хотя n большой, он меньше, чемNumber.MAX_VALUE, так почему я вижу такое странное поведение?

Я подумал, что, возможно, это проблема с форматированием больших чисел при выводе trace, но это не объясняет n + 4 - n == 8

Это какая-то странная проблема с числами с плавающей запятой?

Ответы [ 5 ]

3 голосов
/ 27 сентября 2011

Да, это проблема с плавающей запятой, но она не странная.Это все ожидаемое поведение.

Числовой тип данных в AS3 на самом деле является «64-битным форматом с двойной точностью, как определено стандартом IEEE для двоичной арифметики с плавающей точкой (IEEE-754)» ( source ).Поскольку число, которое вы присвоили n , имеет слишком много цифр, чтобы поместиться в эти 64 бита, оно округляется, и это является причиной всех «странных» результатов.

Если вам нужночтобы выполнить точную арифметику больших целых чисел, вам нужно будет использовать пользовательский класс больших целых чисел, например this .

1 голос
/ 17 октября 2017

Чтобы быть в безопасности с целочисленной математикой при использовании чисел, я проверил документацию AS3 на число, и в нем говорится:

Класс Number можно использовать для представления целых значенийвне допустимого диапазона типов данных int и uint.Тип данных Number может использовать до 53 бит для представления целочисленных значений по сравнению с 32 битами, доступными для int и uint.

53-битное целое число возвращает вас к 2 ^ 53 - 1, если яЯ не ошибаюсь, что составляет 9007199254740991, или около 9 квадриллионов.Остальные 11 битов, которые помогают составить 64-битное число, используются в показателе степени.Число, использованное в вопросе, составляет около 64,3 квадриллиона.Чтобы пройти эту точку (9 квадриллионов), требуется больше битов для значащей части числа (мантиссы), чем выделено, и поэтому происходит округление.Полезное видео , объясняющее, почему это имеет смысл (по серии Infinite от PBS Studio).

Так что да, нужно искать внешние ресурсы, такие как BigInt.Надеюсь, ресурсы, на которые я ссылаюсь, кому-нибудь пригодятся.

1 голос
/ 27 сентября 2011

У нас есть реализация as3 BigDecimal, скопированная с Java, которую мы используем для ВСЕХ вычислений.В торговом приложении ошибки с плавающей запятой были неприемлемы.

1 голос
/ 27 сентября 2011

Числа во флэш-памяти являются числами с плавающей запятой двойной точности.Это означает, что они хранят ряд значащих цифр и показатель степени.Это способствует большему диапазону выражаемых чисел по сравнению с точностью чисел из-за ограничений памяти.В какой-то момент для чисел с большим количеством значащих цифр произойдет округление.Что вы видите;наименее значимые цифры округляются.Google с двойной точностью чисел с плавающей точкой, и вы найдете кучу технической информации о том, почему.

Это тип данных.Если вам нужны точные числа, вы должны придерживаться целых чисел на основе uint или int.Другие языки имеют библиотеки обработки чисел с фиксированной запятой или bigint (иногда называемые BigInt или Decimal), которые являются обертками вокруг целых и длинных чисел для выражения гораздо больших чисел за счет потребления памяти.

0 голосов
/ 27 сентября 2011

Это действительно проблема аппроксимации чисел с плавающей запятой.

Я полагаю, что n больше, чем 4, поэтому он должен придерживаться детей своего возраста: trace(n - n + 4) нормально, так как n-n = 0; 0 + 4 = 4;

На самом деле Number - это не тип, который будет использоваться для больших целых чисел, а числа с плавающей запятой. Если вы хотите вычислить большие целые числа, вы должны оставаться в пределах uint.MAX_VALUE.

Ура!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...