Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/apache-flex/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache flex 如何处理Actionscript中的数字精度?_Apache Flex_Actionscript 3_Actionscript - Fatal编程技术网

Apache flex 如何处理Actionscript中的数字精度?

Apache flex 如何处理Actionscript中的数字精度?,apache-flex,actionscript-3,actionscript,Apache Flex,Actionscript 3,Actionscript,我用BlazeDS将BigDecimal对象序列化为Actionscript。一旦它们作为数字对象点击Actionscript,它们的值如下: 140475.32变为140475.3199999998 我该怎么处理?问题是,如果使用精度为2的a,则该值将被截断为140475.31。有什么想法吗?如果您事先知道所需的精度,您可以存储按比例缩放的数字,以便所需的最小数量是一个整数值。例如,将数字存储为美分而不是美元 如果这不是一个选项,那么像这样的东西怎么样: function printTwoDe

我用BlazeDS将BigDecimal对象序列化为Actionscript。一旦它们作为数字对象点击Actionscript,它们的值如下:

140475.32
变为
140475.3199999998


我该怎么处理?问题是,如果使用精度为2的a,则该值将被截断为
140475.31
。有什么想法吗?

如果您事先知道所需的精度,您可以存储按比例缩放的数字,以便所需的最小数量是一个整数值。例如,将数字存储为美分而不是美元

如果这不是一个选项,那么像这样的东西怎么样:

function printTwoDecimals(x)
{
   printWithNoDecimals(x);
   print(".");
   var scaled = Math.round(x * 100);
   printWithNoDecimals(scaled % 100);
}
(无论如何,打印时没有小数。)


不过,这对真正大的数字不起作用,因为仍然可能会失去精度

这是我针对这个问题的通用解决方案(我有):

例如:

  • 0.12345678
    乘以
    10
    ;这给了我们
    1.2345678
  • 当我们取整
    1.2345678
    时,我们得到
    1.0
  • 最后,
    1.0
    除以
    10
    等于
    0.1
另一个例子:

  • 1.7302394309234435
    乘以
    10000
    ;这给我们提供了
    17302.394309234435
  • 当我们取整
    17302.394309234435时,我们得到
    17302
  • 最后,
    17302
    除以
    10000
    等于
    1.7302

编辑

基于匿名答案,对该方法的参数进行了很好的简化,使精度更加直观。e、 g:


注意:我在这里添加了这个,以防有人将此视为答案而不向下滚动…

这似乎更像是一个交通问题,数字是正确的,但比例忽略了。如果必须将数字存储为服务器上的BigDecimal,则在发送之前,您可能希望将其转换为服务器端不太含糊的格式(数字、双精度、浮点)。

您可以使用property:rounding=“nearest”

在NumberFormatter中,舍入有4个值可供选择:舍入=“无|向上|向下|最近”。我想根据你的情况,你可以选择“最近的”


--chary--

我在ActionScript3中使用了
Number.toFixed(precision)
来执行此操作:

它正确处理舍入并指定小数点后要显示的位数,这与限制要显示的总位数而不考虑小数点位置的
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));                                                

我将BigDecimal的Java转换为ActionScript。 我们没有选择,因为我们计算的是财务应用


对于任何感兴趣的人来说,这只是功能上的细微变化

function setPrecision(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

我发现BlazeDS还支持将Java BigDecimal对象序列化为ActionScript字符串。因此,如果您不需要ActionScript数据是数字(您在Flex/ActionScript方面没有做任何数学运算),那么字符串映射工作得很好(没有四舍五入的奇怪之处)。有关BlazeDS映射选项,请参见此链接:

您可以在Flash PLayer Jira bug跟踪系统中投票并观看增强请求,网址为

同时使用Number.toFixed()解决问题请参见: ()

或者使用开源实现:()或()


至于序列化工作,如果您使用Blazeds或LCD,它将很小,因为它们支持Java BigDecimal序列化(到字符串)cf.()

GraniteDS 2.2在ActionScript3中有BigDecimal、BigInteger和Long实现,Java/Flex之间的序列化选项用于这些类型,甚至还有代码生成工具选项,以便为相应的Java变量生成3个大数字变量


请参阅此处的更多信息:。

我们能够通过从AMF3Output中进行子类化,重用web上的一个可用BigDecimal.as类和扩展blazeds,您需要在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);
        }
    }
}
就这么简单!然后您就可以使用blazeds获得本机的BigDecimal支持,哇哦! 确保BigDecimal as3类实现IExternalizable


干杯,jb

伙计们,检查一下解决方案:

protected function button1_clickHandler(event:MouseEvent):void { var formatter:NumberFormatter = new NumberFormatter(); formatter.precision = 2; formatter.rounding = NumberBaseRoundType.NEAREST; var a:Number = 14.31999999999998; trace(formatter.format(a)); //14.32 } 受保护的功能按钮1\u clickHandler(事件:MouseeEvent):无效 { var格式化程序:NumberFormatter=newnumberformatter(); formatter.precision=2; formatter.rounding=NumberBaseRoundType.NEAREST; 变量a:数字=14.319999998; 跟踪(formatter.format(a));//14.32 }
我为Actionscript客户端移植了BigDecimal的IBM ICU实现。我们的版本添加了一些方便的比较方法

您可以扩展Blaze AMF端点以添加对BigDecimal的序列化支持。请注意,另一个答案中的代码似乎不完整,根据我们的经验,它在生产中无法工作

AMF3假设重复的对象、特征和字符串通过引用发送。序列化时,对象引用表需要保持同步,否则客户端将在反序列化期间丢失这些表的同步,并开始抛出类强制转换错误,或损坏不匹配但强制转换为ok的字段中的数据

以下是更正后的代码:

public void writeObject(final Object o) throws IOException {
    if (o instanceof BigDecimal) {
        write(kObjectType);
        if(!byReference(o)){   // if not previously sent
            String s = ((BigDecimal)o).toString();                  
            TraitsInfo ti = new TraitsInfo("java.math.BigDecimal",false,true,0);
            writeObjectTraits(ti); // will send traits by reference
            writeUTF(s);
            writeObjectEnd();  // for your AmfTrace to be correctly indented
        }
    } else {
            super.writeObject(o);
        }
}
还有另一种发送类型化对象的方法,它不需要在客户端上外部化。客户端将改为在对象上设置textValue属性:

TraitsInfo ti = new TraitsInfo("java.math.BigDecimal",false,false,1);           
ti.addProperty("textValue");
writeObjectTraits(ti);
writeObjectProperty("textValue",s);
无论哪种情况,Actionscript类都需要以下标记:

[RemoteClass(alias="java.math.BigDecimal")]
Actionscript类还需要一个文本属性来匹配您选择发送的将初始化BigDecimal值的文本属性,或者在可外部化对象的情况下,需要两个如下方法:

public  function writeExternal(output:IDataOutput):void {       
    output.writeUTF(this.toString());
}
public  function readExternal(input:IDataInput):void {          
    var s:String = input.readUTF();
    setValueFromString(s);
}
public class BigNumberWrapper implements Externalizable {

    String stringValue;
    String className;

    public void readExternal(ObjectInput arg0) throws IOException, ClassNotFoundException {
        stringValue = arg0.readUTF();       
    }

    public void writeExternal(ObjectOutput arg0) throws IOException {
        arg0.writeUTF(stringValue);     
    }

    public String getStringValue() {
        return stringValue;
    }

    public void setStringValue(String stringValue) {
        this.stringValue = stringValue;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

}

TraitsInfo ti = new TraitsInfo("java.math.BigDecimal",false,false,1); ti.addProperty("textValue"); writeObjectTraits(ti); writeObjectProperty("textValue",s);

[RemoteClass(alias="java.math.BigDecimal")]
public  function writeExternal(output:IDataOutput):void {       
    output.writeUTF(this.toString());
}
public  function readExternal(input:IDataInput):void {          
    var s:String = input.readUTF();
    setValueFromString(s);
}
public class BigNumberProxy extends AbstractProxy {

    public BigNumberProxy() {
        this(null);
    }

    public BigNumberProxy(Object defaultInstance) {
        super(defaultInstance);
        this.setExternalizable(true);

        if (defaultInstance != null)
           alias = getClassName(defaultInstance);
    }   

    protected String getClassName(Object instance) {
        return((BigNumberWrapper)instance).getClassName();
    }

    public Object createInstance(String className) {
        BigNumberWrapper w = new BigNumberWrapper();
        w.setClassName(className);
        return w;
    }

    public Object instanceComplete(Object instance) {
    String desiredClassName = ((BigNumberWrapper)instance).getClassName();
    if(desiredClassName.equals("java.math.BigDecimal"))
        return new BigDecimal(((BigNumberWrapper)instance).stringValue);
    return null;
}

    public String getAlias(Object instance) {
        return((BigNumberWrapper)instance).getClassName();
    }

}
PropertyProxyRegistry.getRegistry().register(
    java.math.BigDecimal.class, new BigNumberProxy());
public class BigNumberWrapper implements Externalizable {

    String stringValue;
    String className;

    public void readExternal(ObjectInput arg0) throws IOException, ClassNotFoundException {
        stringValue = arg0.readUTF();       
    }

    public void writeExternal(ObjectOutput arg0) throws IOException {
        arg0.writeUTF(stringValue);     
    }

    public String getStringValue() {
        return stringValue;
    }

    public void setStringValue(String stringValue) {
        this.stringValue = stringValue;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

}
public function setPrecision(number:Number, precision:int):Number {
precision = Math.pow(10, precision);

const excelFactor : Number = 0.00000001;

number += excelFactor;

return (Math.round(number * precision)/precision);
}