Как иметь дело с точностью Числа в Actionscript?

Это решение проверяет EmployeeFileHandler и показывает ошибку, если, например, каталог недоступен для записи. Запустите с javac EmployeeFileHandler.java; java -ea EmployeeFileHandler, чтобы сбой при подтверждении. Убедитесь, что класс Person также сериализуем.

import java.util.*;
import java.io.*;

public class EmployeeFileHandler implements Serializable {
    public static void main(String[] args) {
        ArrayList<Employees> employees = new ArrayList<Employees>();
        for (int i = 0; i < 1000; i++) {
            employees.add(new Employees("Name" + i, "Surname" + i, "" + i, 12345678));
        }        
        writeDate(employees);

        ArrayList<Employees> employees2 = new ArrayList<Employees>();
        readData(employees2);

        assert employees.size() == employees2.size();
        for (int i = 0; i < 1000; i++) {
            Employees e = employees2.get(i);
            assert e.Name.equals("Name" + i);
            assert e.Surname.equals("Surname" + i);
            assert e.ID.equals("" + i);
            assert e.MobNo == 12345678;
        }        
    }

    public static void readData(ArrayList<Employees> listIn) {

        boolean endOfFile = false;
        Employees temp;

        try {

            FileInputStream employeesFile = new FileInputStream("employee.obf");
            ObjectInputStream employeesStream = new ObjectInputStream(employeesFile);
            temp = (Employees) employeesStream.readObject();

            while (endOfFile != true) {
                try {
                    listIn.add(temp);
                    temp = (Employees) employeesStream.readObject();
                } catch (EOFException e) {
                    endOfFile = true;
                }
            }
            employeesStream.close();
        }

        catch (FileNotFoundException e) {
            System.out.println("Employee file was not found");
        } catch (IOException e) {
            System.out.println("Employee file could not be read");
        } catch (ClassNotFoundException e) {
            System.out.println("Employee class was not found");
        }
    }

    public static void writeDate(ArrayList<Employees> employee) {

        try {
            FileOutputStream EmployeesFile = new FileOutputStream("employee.obf");
            ObjectOutputStream EmployeesStream = new ObjectOutputStream(EmployeesFile);

            for (Employees employees : employee) {
                EmployeesStream.writeObject(employees);
            }
            EmployeesStream.close();
        } catch (IOException e) {
            // System.out.println("Error occurred while saving");
            e.printStackTrace();
        }
    }
}
18
задан someOne 18 January 2017 в 11:22
поделиться

11 ответов

Это - мое универсальное решение для проблемы (я имею занесенный в блог об этом здесь ) :

var toFixed:Function = function(number:Number, factor:int) {
  return Math.round(number * factor)/factor;
}

, Например:

trace(toFixed(0.12345678, 10)); //0.1
  • Умножаются 0.12345678 на 10; это дает нам 1.2345678.
  • то, Когда мы раунд 1.2345678, мы становимся 1.0,
  • и наконец, 1.0 разделенными на [1 110], равняется 0.1.

Другой пример:

trace(toFixed(1.7302394309234435, 10000)); //1.7302
  • Умножаются 1.7302394309234435 на [1 113]; это дает нам 17302.394309234435.
  • то, Когда мы раунд 17302.394309234435 мы становимся 17302,
  • и наконец, 17302 разделенными на [1 118], равняется 1.7302.

<час> Редактирование

На основе анонимного ответа ниже , существует хорошее упрощение для параметра на методе, который делает точность намного более интуитивной. , например:

var setPrecision:Function = function(number:Number, precision:int) {
 precision = Math.pow(10, precision);
 return Math.round(number * precision)/precision;
}

var number:Number = 10.98813311;
trace(setPrecision(number,1)); //Result is 10.9
trace(setPrecision(number,2)); //Result is 10.98
trace(setPrecision(number,3)); //Result is 10.988 and so on

N.B. Я добавил это здесь на всякий случай, любой рассматривает это как ответ и не прокручивает вниз...

33
ответ дан 30 November 2019 в 05:47
поделиться

Это больше походит на транспортную проблему, при этом число корректно, но проигнорированный масштаб. Если число должно быть сохранено как BigDecimal на сервере, можно хотеть преобразовать его сторона сервера в менее неоднозначный формат (Число, дважды, Плавание) прежде, чем отправить его.

-1
ответ дан 30 November 2019 в 05:47
поделиться

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

, Если это не опция, как насчет чего-то вроде этого:

function printTwoDecimals(x)
{
   printWithNoDecimals(x);
   print(".");
   var scaled = Math.round(x * 100);
   printWithNoDecimals(scaled % 100);
}

(С однако Вами печатают без десятичных чисел, застрявших там.)

Это не будет работать на действительно большие числа, тем не менее, потому что можно все еще потерять точность.

0
ответ дан 30 November 2019 в 05:47
поделиться

Вы можете использовать свойство: rounding = "ближайший"

В NumberFormatter округление имеет 4 значения, которые вы можете выбрать: rounding = "none | up | down | ближайший". Я думаю, что в вашей ситуации вы можете выбрать rounding = "ближайший".

- chary -

1
ответ дан 30 November 2019 в 05:47
поделиться

Для этого я использовал Number.toFixed (precision) в ActionScript 3: http://livedocs.adobe.com/flex/3/langref/Number.html#toFixed % 28% 29

он правильно обрабатывает округление и указывает количество отображаемых цифр после десятичной дроби - в отличие от Number.toPrecision () , который ограничивает общее количество отображаемых цифр независимо от положения десятичный.

var roundDown:Number = 1.434;                                             
// will print 1.43                                                        
trace(roundDown.toFixed(2));                                              

var roundUp:Number = 1.436;                                               
// will print 1.44                                                        
trace(roundUp.toFixed(2));                                                
10
ответ дан 30 November 2019 в 05:47
поделиться

Just a slight variation on Frasers Function, for anyone who is interested.

function setPrecision(number:Number, precision:int) {
 precision = Math.pow(10, precision);
 return (Math.round(number * precision)/precision);
}

So to use:

var number:Number = 10.98813311;
trace(setPrecision(number,1)); //Result is 10.9
trace(setPrecision(number,2)); //Result is 10.98
trace(setPrecision(number,3)); //Result is 10.988 and so on
20
ответ дан 30 November 2019 в 05:47
поделиться

Я преобразовал Java из BigDecimal в ActionScript. У нас не было выбора, поскольку мы выполняем вычисления для финансовых приложений.

http://code.google.com/p/bigdecimal/

4
ответ дан 30 November 2019 в 05:47
поделиться

Я обнаружил, что BlazeDS также поддерживает сериализацию объектов Java BigDecimal в строки ActionScript. Поэтому, если вам не нужно, чтобы данные ActionScript были числами (вы не выполняете никаких математических расчетов на стороне Flex / ActionScript), тогда сопоставление String работает хорошо (без странностей с округлением). См. Эту ссылку для параметров сопоставления BlazeDS: http://livedocs.adobe.com/blazeds/1/blazeds_devguide/help.html?content=serialize_data_2.html

1
ответ дан 30 November 2019 в 05:47
поделиться

Вы можете проголосовать и посмотреть запрос на улучшение в системе отслеживания ошибок Flash PLayer Jira по адресу https://bugs.adobe.com / jira / browse / FP-3315

А пока используйте обходной путь Number.toFixed (), см.: ( http://livedocs.adobe.com/flex/3/langref/Number.html#toFixed%28%29 )

или используйте существующие реализации с открытым исходным кодом: ( http : //code.google.com/p/bigdecimal/ ) или ( http://www.fxcomps.com/money.html )

Что касается усилий по сериализации, ну, он будет небольшим, если вы используете Blazeds или LCDS, поскольку они поддерживают сериализацию Java BigDecimal (в String) cf. ( http://livedocs.adobe.com/livecycle/es/sdkHelp/programmer/lcds/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=serialize_data_3.html )

0
ответ дан 30 November 2019 в 05:47
поделиться

GraniteDS 2.2 имеет реализации BigDecimal, BigInteger и Long в ActionScript3, параметры сериализации между Java / Flex для этих типов и даже параметры инструментов генерации кода для создания переменных больших чисел AS3 для соответствующей Java. единицы.

Подробнее см. Здесь: http://www.graniteds.org/confluence/display/DOC22/2.+Big+Number+Implementations .

1
ответ дан 30 November 2019 в 05:47
поделиться

Нам удалось повторно использовать один из доступных классов BigDecimal.as в Интернете и расширить blazed путем подкласса из AMF3Output, вам нужно будет указать свой собственный класс конечной точки в файлах flex xml, в эту пользовательскую конечную точку вы можете вставить ваш собственный сериализатор, который создает экземпляр подкласса AMF3Output.

public class EnhancedAMF3Output extends Amf3Output {

    public EnhancedAMF3Output(final SerializationContext context) {
        super(context);
    }

    public void writeObject(final Object o) throws IOException {           
        if (o instanceof BigDecimal) {
            write(kObjectType);
            writeUInt29(7); // write U290-traits-ext (first 3 bits set)
            writeStringWithoutType("java.math.BigDecimal");
            writeAMFString(((BigDecimal)o).toString());
        } else {
            super.writeObject(o);
        }
    }
}

Так просто! тогда у вас есть встроенная поддержка BigDecimal с использованием blazed, wooohoo! Убедитесь, что ваш класс BigDecimal as3 реализует IExternalizable

ура, jb

1
ответ дан 30 November 2019 в 05:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: