2013-10-23 27 views
3

我的Perl版本支持64位。我從多個來源接收JSON數據,然後對其進行解碼,處理,然後對其進行重新編碼,以便將數據保存到MySQL隊列中供其他服務器進一步處理。在Perl中使用JSON :: XS :: encode_json將64位整數更改爲浮點

所有數據都包含64位整數作爲標識符。有時候,在某些我不明白的情況下,64位整數會被更改爲浮點值JSON :: XS :: encode_json。例如,393074769794314240將更改爲3.93074769794314e+17

我該如何防止這種情況發生?

謝謝。

+0

是否可以將標識符編碼爲原始JSON中的字符串?例如'「123」'而不是'123'? – AKHolland

+0

是的,它可能是一個選項。但是,我不理解爲什麼值會從整數變爲浮點數,這讓我感到非常不舒服。 – calvillo

回答

3

如果整數在浮點上下文中使用,我可以複製該問題。在浮點運算中使用該數字就足夠了,例如,增加另一個浮點數。下面是一個示例腳本:

use strict; 
use JSON::XS qw(encode_json); 
use Devel::Peek; 

{ 
    my $x = { number => 4_999_999_999_999_999}; 
    Dump $x->{number}; 
    warn encode_json $x; # encodes number as integer 
} 

{ 
    my $x = { number => 4_999_999_999_999_999}; 
    my $y = $x->{number} + 0.1; 
    Dump $x->{number}; 
    warn encode_json $x; # encodes number as float 
} 

在我的FreeBSD AMD64系統我得到

SV = IV(0x80180a458) at 0x80180a468 
    REFCNT = 1 
    FLAGS = (IOK,pIOK) 
    IV = 4999999999999999 
{"number":4999999999999999} at /tmp/json3.pl line 22. 
SV = PVNV(0x80184d930) at 0x801813408 
    REFCNT = 1 
    FLAGS = (IOK,NOK,pIOK,pNOK) 
    IV = 4999999999999999 
    NV = 5e+15 
    PV = 0 
{"number":5e+15} at /tmp/json3.pl line 29. 

一種解決方法是encode_json調用之前使用類似$x->{number} += 0; - 這將刪除的NV值(浮點值),並且JSON :: XS將再次只能看到一個IV(整數值)。

+0

非常感謝。 '$ x - > {number} + = 0;'現在就做好了。現在我只需要了解它爲什麼會更改爲浮點上下文。 – calvillo

+0

'+ 0.1'只是一種可能性。它也可以是'printf'%f \ n「,$ x - > {number}'或'log($ x - > {number})'或'$ x - > {number} ** 2' ... –

2

我無法複製您的問題。

use Config  qw(%Config); 
use Devel::Peek qw(Dump); 
use JSON::XS qw(encode_json decode_json); 

print $Config{uvsize} * 8, "-bit ints\n"; 
my $n = 393074769794314240; 
printf("%.20g\n", 0+$n); 
Dump($n); 
my $json = encode_json([$n]); 
print "$json\n"; 
Dump(decode_json($json)->[0]); 

輸出:

64-bit ints 
393074769794314240 
SV = IV(0x4c8d90) at 0x4c8da0 
    REFCNT = 1 
    FLAGS = (PADMY,IOK,pIOK) 
    IV = 393074769794314240 
[393074769794314240] 
SV = IV(0x1dd130) at 0x1dd140 
    REFCNT = 1 
    FLAGS = (IOK,pIOK) 
    IV = 393074769794314240 

除非我把它作爲一個浮點數,說用

printf("%.20g\n", $n); 

今後更換

printf("%.20g\n", 0+$n); 

  • 這不太可能有幫助,但您可以嘗試升級JSON :: XS。
  • 提供一個最小的,可運行的問題演示。
  • 提供perl -V:ivsize的輸出。
+0

更新了我的答案。 – ikegami

+0

'perl -V:ivsize'的輸出是'ivsize ='8';'。我想這意味着64位。 – calvillo

+0

然後,你必須有浮點數而不是整數,也許像我之前提到的那樣使用printf%f,也許是由於其他浮點操作。你看過你的代碼嗎? – ikegami