How to deal with Number precision in Actionscript?

2019-01-06 14:17发布

I have BigDecimal objects serialized with BlazeDS to Actionscript. Once they hit Actionscript as Number objects, they have values like:

140475.32 turns into 140475.31999999999998

How do I deal with this? The problem is that if I use a NumberFormatter with precision of 2, then the value is truncated to 140475.31. Any ideas?

14条回答
Emotional °昔
2楼-- · 2019-01-06 14:30

I discovered that BlazeDS supports serializing Java BigDecimal objects to ActionScript Strings as well. So if you don't need the ActionScript data to be Numbers (you are not doing any math on the Flex / ActionScript side) then the String mapping works well (no rounding weirdness). See this link for the BlazeDS mapping options: http://livedocs.adobe.com/blazeds/1/blazeds_devguide/help.html?content=serialize_data_2.html

查看更多
家丑人穷心不美
3楼-- · 2019-01-06 14:35

We were able to reuse one of the available BigDecimal.as classes on the web and extended blazeds by sublassing from AMF3Output, you'll need to specify your own endpoint class in the flex xml files, in that custom endpoint you can insert your own serializer that instantiates an AMF3Output subclass.

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);
        }
    }
}

as simple as that! then you have native BigDecimal support using blazeds, wooohoo! Make sure your BigDecimal as3 class implements IExternalizable

cheers, jb

查看更多
Root(大扎)
4楼-- · 2019-01-06 14:37

This is my generic solution for the problem (I have blogged about this here):

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

For example:

trace(toFixed(0.12345678, 10)); //0.1
  • Multiply 0.12345678 by 10; that gives us 1.2345678.
  • When we round 1.2345678, we get 1.0,
  • and finally, 1.0 divided by 10 equals 0.1.

Another example:

trace(toFixed(1.7302394309234435, 10000)); //1.7302
  • Multiply 1.7302394309234435 by 10000; that gives us 17302.394309234435.
  • When we round 17302.394309234435 we get 17302,
  • and finally, 17302 divided by 10000 equals 1.7302.


Edit

Based on the anonymous answer below, there is a nice simplification for the parameter on the method that makes the precision much more intuitive. e.g:

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. I added this here just in case anyone sees this as the answer and doesn't scroll down...

查看更多
趁早两清
5楼-- · 2019-01-06 14:38

GraniteDS 2.2 has BigDecimal, BigInteger and Long implementations in ActionScript3, serialization options between Java / Flex for these types, and even code generation tools options in order to generate AS3 big numbers variables for the corresponding Java ones.

See more here: http://www.graniteds.org/confluence/display/DOC22/2.+Big+Number+Implementations.

查看更多
Explosion°爆炸
6楼-- · 2019-01-06 14:42

You may vote and watch the enhancement request in the Flash PLayer Jira bug tracking system at https://bugs.adobe.com/jira/browse/FP-3315

And meanwhile use the Number.toFixed() work-around see : (http://livedocs.adobe.com/flex/3/langref/Number.html#toFixed%28%29)

or use the open source implementations out there : (http://code.google.com/p/bigdecimal/) or (http://www.fxcomps.com/money.html)

As for the serialization efforts, well, it will be small if you use Blazeds or LCDS as they do support Java BigDecimal serialization (to 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)

查看更多
我只想做你的唯一
7楼-- · 2019-01-06 14:44

I converted the Java of BigDecimal to ActionScript. We had no choices since we compute for financial application.

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

查看更多
登录 后发表回答