BlazeDSでActionscriptにシリアル化されたBigDecimalオブジェクトがあります。アクションスクリプトをNumberオブジェクトとしてヒットすると、次のような値になります。
140475.32
は140475.31999999999998
に変わります
どうすればこれに対処できますか?問題は、精度2で NumberFormatter を使用すると、値が140475.31
に切り捨てられることです。何か案は?
Frasers 関数のほんの少しのバリエーション、興味のある人のために。
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
これを行うためにActionScript3でNumber.toFixed(precision)
を使用しました: 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));
BigDecimalのJava=をActionScriptに変換しました。金融アプリケーションを計算するため、選択肢がありませんでした。
GraniteDS 2.2には、ActionScript3でのBigDecimal、BigInteger、およびLongの実装、これらのタイプのJava/Flex間のシリアル化オプション、および対応するJava変数のAS3大きな数値変数を生成するためのコード生成ツールオプションがあります。
詳細はこちら: http://www.graniteds.org/confluence/display/DOC22/2.+Big+Number+Implementations 。
Webで利用可能なBigDecimal.asクラスの1つを再利用でき、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サポートがあります。 BigDecimalas3クラスがIExternalizableを実装していることを確認してください
乾杯、jb
みんな、解決策をチェックしてください:
保護された関数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 }
プロパティを使用できます:rounding = "nearest"
NumberFormatterでは、丸めには4つの値を選択できます:rounding = "none | up | down | nearest"。あなたの状況では、丸め=「最も近い」を選択できると思います。
-チャリー-
IBMを移植しましたICU Actionscriptクライアント用のBigDecimalの実装です 他の誰かがほぼ同じバージョンをここでgoogleコードプロジェクトとして公開しています。 私たちのバージョンはいくつかの便利なメソッドを追加しています比較を行うため。
Blaze AMFエンドポイントを拡張して、BigDecimalのシリアル化サポートを追加できます。他の回答のコードは不完全に見え、私たちの経験では、本番環境では機能しないことに注意してください。
AMF3は、重複するオブジェクト、特性、および文字列が参照によって送信されることを前提としています。オブジェクト参照テーブルは、シリアル化中に同期を維持する必要があります。そうしないと、クライアントは、逆シリアル化中にこれらのテーブルの同期を失い、クラスキャストエラーをスローし始めます。
修正されたコードは次のとおりです。
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);
}
}
型付きオブジェクトを送信する別の方法があります。これは、クライアントでExternalizableを必要としません。クライアントは、代わりにオブジェクトに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値を初期化するプロパティに一致するテキストプロパティ、またはExternalizableオブジェクトの場合は、次のようないくつかのメソッドも必要です。
public function writeExternal(output:IDataOutput):void {
output.writeUTF(this.toString());
}
public function readExternal(input:IDataInput):void {
var s:String = input.readUTF();
setValueFromString(s);
}
このコードは、サーバーからクライアントに送られるデータにのみ関係します。クライアントからサーバーへと逆方向に逆シリアル化するために、AbstractProxyを拡張し、ラッパークラスを使用して、実際のオブジェクトが作成される前にBigDecimalの文字列値を一時的に格納することを選択しました。これは、BigDecimalをインスタンス化してからインスタンス化できないためです。 Blaze/LCDSの設計はすべてのオブジェクトに当てはまるはずであるため、値を割り当てます。
デフォルトの処理を回避するためのプロキシオブジェクトを次に示します。
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;
}
}
驚いたことに、MS Excelのラウンド関数は、上記で示したものとは異なる値を提供します。たとえばExcelで
Round(143,355;2)
= 143,36
したがって、Excelラウンドの回避策は次のようになります。
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);
}
BlazeDSがJava BigDecimalオブジェクトのActionScript文字列へのシリアル化もサポートしていることを発見しました。したがって、ActionScriptデータを数値にする必要がない場合(Flex/ActionScript側で計算を行っていない場合) )その後、文字列マッピングは適切に機能します(丸めの奇妙さはありません)。BlazeDSマッピングオプションについては、次のリンクを参照してください: http://livedocs.Adobe.com/blazeds/1/blazeds_devguide/help.html?content=serialize_data_2。 html
必要な精度が事前にわかっている場合は、必要な最小量が全体の値になるようにスケーリングされた数値を格納できます。たとえば、数値をドルではなくセントとして保存します。
それがオプションではない場合、次のようなものはどうですか:
function printTwoDecimals(x)
{
printWithNoDecimals(x);
print(".");
var scaled = Math.round(x * 100);
printWithNoDecimals(scaled % 100);
}
(ただし、小数点以下を表示しないで印刷します。)
ただし、精度が低下する可能性があるため、これはreally大きな数値では機能しません。
https://bugs.Adobe.com/jira/browse/FP-3315 のFlash PLayer Jiraバグ追跡システムで投票し、機能強化のリクエストを見ることができます。
その間、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シリアル化(文字列へ)cf。( http:// livedocs .Adobe.com/livecycle/es/sdkHelp/programmer/lcds/wwhelp/wwhimpl/common/html/wwhelp.htm?context = LiveDocs_Parts&file = serialize_data_3.html )