MongoDB 집계 프레임워크를 사용하여 소수점 이하 2자리로 반올림
나는 mongodb 집계 프레임워크를 사용하고 있으며 아래와 같이 몇 가지 계산을 하고 있습니다.
db.RptAgg.aggregate(
{$group: {
_id: {Region: "$RegionTxt", Mth: "$Month"},
ActSls: {$sum:"$ActSls"},
PlnSls: {$sum:"$PlnSls"}
}},
{$project: {
ActSls: 1,
PlnSls: 1,
ActToPln: {$cond: [
{$ne: ["$PlnSls", 0]},
{$multiply: [{$divide: ['$ActSls', '$PlnSls']}, 100]},
0
]}
}}
);
저는 제 결과를 소수점 2자리로 반올림하는 가장 좋고 쉬운 방법을 찾고 있습니다.제 결과는 다음과 같습니다.
{
"result": [{
"_id": {
"Region": "East",
"Mth": 201301
},
"ActSls": 72,
"PlnSls": 102,
"ActToPln": 70.58823529411765
}],
"ok": 1
}
저는 "ActToPln" 대신 "ActToPln"이 70.59를 표시하기를 원합니다: 70.58823529411765, 집계 프레임워크 자체의 결과입니다.응용프로그램에서 반올림을 피하고 싶습니다.
당신은 그것을 도와줄 수 있습니까?
제가 사용한 데이터 세트는 다음과 같습니다.
{
"_id" : ObjectId("51d67ef69557c507cb172572"),
"RegionTxt" : "East",
"Month" : 201301,
"Date" : "2013-01-01",
"ActSls" : 31,
"PlnSls" : 51
}
{
"_id" : ObjectId("51d67ef69557c507cb172573"),
"RegionTxt" : "East",
"Month" : 201301,
"Date" : "2013-01-02",
"ActSls" : 41,
"PlnSls" : 51
}
잘 부탁드립니다.난두
거기에는 없다$round
연산자를 사용할 수 있지만 집계 프레임워크에서 이 작업을 수행할 수 있습니다. 특정 순서로 수행하면 일반적으로 부동 소수점 정밀도 문제를 피할 수 있습니다.
> db.a.save({x:1.23456789})
> db.a.save({x:9.87654321})
> db.a.aggregate([{$project:{ _id:0,
y:{$divide:[
{$subtract:[
{$multiply:['$x',100]},
{$mod:[{$multiply:['$x',100]}, 1]}
]},
100]}
}}])
{ "y" : 1.23 }
{ "y" : 9.87 }
문제의 기존 파이프라인을 고려하여 다음을 교체합니다.
{$multiply:[{$divide: ['$ActSls', '$PlnSls']},100]}
와 함께
{$divide:[
{$subtract:[
{$multiply:[
{$divide: ['$ActSls','$PlnSls']},
10000
]},
{$mod:[
{$multiply:[{$divide: ['$ActSls','$PlnSls']}, 10000 ]},
1]}
]},
100
]}
샘플 데이터 포인트의 결과는 다음과 같습니다.
{ "ActSls" : 31, "PlnSls" : 51, "ActToPln" : 60.78 }
{ "ActSls" : 41, "PlnSls" : 51, "ActToPln" : 80.39 }
{ "ActSls" : 72, "PlnSls" : 102, "ActToPln" : 70.58 }
시작으로, 특정 정밀도를 가진 숫자를 지정된 소수점 이하로 반올림하는 데 사용할 수 있는 새로운 집계 연산자가 있습니다.
$round : [ <번호>, <장소> ] }
집계 파이프라인 내에서 이와 같이 사용할 수 있는 항목(여기서는 설명)x
스토2
소수점 이하):
// db.collection.insert([{x: 1.23456}, {x: 9.87654}, {x: 0.055543}, {x: 12.345}])
db.collection.aggregate([{ $project: { "rounded_x": { $round: ["$x", 2] }}}])
// [{"rounded_x": 1.23}, {"rounded_x": 9.88}, {"rounded_x": 0.06}, {"rounded_x": 12.35}]
참고:place
매개 변수는 선택 사항이며, 매개 변수를 생략하면 전체 정수로 반올림됩니다(즉, 소수점 0자리 반올림).
이유는 모르겠지만 (이 페이지의) 모든 답변이 나에게 제공됩니다.12.34
위해서12.345
그래서 저는 제 프로젝트 단계를 작성했습니다.
x = 12.345
{'$project': {
y: {'$divide': [{'$trunc': {'$add': [{'$multiply': ['$x', 100]}, 0.5]}}, 100]},
}},
줍니다12.35
.
다음은 간단한 산술이며 트릭은 없습니다.
12.345 * 100 = 1234.5
이 단계를 통해 반올림 위치로 이동합니다.
100 = 10^2
(점 다음에 두 개의 부호).4단계까지 단계의 균형을 다시 맞출 것입니다.1234.5 + 0.5 = 1235.0
여기 내 것이 있습니다.
round half up
.truncate(1235.0) = 1235
부분적인 부분만 삭제하면 됩니다.
1235 / 100 = 12.35
그러나 부정적인 경우에는 올바르게 작동하지 않습니다(내 집계에 충분했습니다).(양성 및 음성) 두 가지 경우 모두에 사용해야 합니다.abs
:
{'$project': {
z: {'$multiply': [
{'$divide': ['$x', {'$abs': '$x'}]},
{'$divide': [{'$trunc': {'$add': [{'$multiply': [{'$abs': '$x'}, 100]}, 0.5]}}, 100]}
]},
}}
여기서 나는 숫자의 부호를 받고, 원래의 숫자를 abs로 감싼 다음, 출력을 반올림하여 곱한 부호를 얻습니다.
이 솔루션은 2dp로 올바르게 올림 또는 내림됩니다.
"rounded" : {
$subtract:[
{$add:['$absolute',0.0049999999999999999]},
{$mod:[{$add:['$absolute',0.0049999999999999999]}, 0.01]}
]
}
예를 들어, 1.2499는 1.25로 반올림하지만 1.2501은 1.25로 반올림합니다.
주의:
- 이 솔루션은 http://www.kamsky.org/stupid-tricks-with-mongodb/rounding-numbers-in-aggregation-framework 의 예를 기반으로 합니다.
- Asya Kamsky의 답변에서 설명에 제시된 변경 사항 이후에도 잘리고 올바르게 올림/다운되지 않는 문제를 해결합니다.
- 추가 요인의 후행 9s 수는 고정밀 입력 숫자를 수용하기 위해 큽니다.반올림할 숫자의 정밀도에 따라 추가 요인을 이보다 더 정확하게 만들어야 할 수도 있습니다.
업데이트(2023년 5월 2일)
라이브러리가 활성 상태로 유지되지 않습니다. 다른 옵션을 고려하십시오.
몽고 라운드는 잘 작동합니다.
예를 들어 다음과 같습니다.3.3333333
var round = require('mongo-round');
db.myCollection.aggregate([
{ $project: {
roundAmount: round('$amount', 2) // it will become 3.33
} }
]);
현재 버전의 집계 프레임워크에는 라운드 연산자가 없습니다.다음 스니펫을 사용해 볼 수 있습니다.
> db.a.save({x:1.23456789})
> db.a.save({x:9.87654321})
> db.a.aggregate([{$project:{y:{$subtract:['$x',{$mod:['$x', 0.01]}]}}}])
{
"result" : [
{
"_id" : ObjectId("51d72eab32549f94da161448"),
"y" : 1.23
},
{
"_id" : ObjectId("51d72ebe32549f94da161449"),
"y" : 9.870000000000001
}
],
"ok" : 1
}
하지만 보시다시피 이 솔루션은 정밀도 문제로 인해 제대로 작동하지 않습니다.이 경우에 가장 쉬운 방법은@wiredprairie
의 충고와 충고round
지원서에 s를 입력합니다.
{$divide:[
{$cond: { if: { $gte: [ {$mod:[{$multiply:['$dollarAmount',100]}, 1]}, 0.5 ] }, then: {$add: [{$subtract:[
{$multiply:['$dollarAmount',100]},
{$mod:[{$multiply:['$dollarAmount',100]}, 1]}
]}
,1]}, else: {$subtract:[
{$multiply:['$dollarAmount',100]},
{$mod:[{$multiply:['$dollarAmount',100]}, 1]}
]} }}
,
100]}
이것들이 반올림에 도움이 될 수 있기를 바랍니다.
rounded:{'$multiply': [{ "$cond": [{ "$gte": [ "$x", 0 ] }, 1,-1 ]},{'$divide': [{'$trunc': {'$add': [{'$multiply': [{'$abs': '$x'}, {$pow:[10,2]}]}, 0.5]}}, {$pow:[10,2]}]}]}
egvo의 솔루션은 멋지지만 0이면 0으로 나눗셈을 제공합니다.$second를 피하려면 기호를 감지하는 데 사용할 수 있습니다.
(x를 field_name으로 바꾸고 숫자 2를 원하는 10진수로 바꿉니다.)
MongoDB가 이 기능을 누락한 것은 유감입니다.저는 그들이 그것을 곧 추가하기를 바랍니다.
하지만, 저는 긴 집계 파이프라인을 생각해냈습니다.인정하건대, 그것은 효율적이지 않을 수도 있지만 반올림의 규칙을 존중합니다.
db.t.aggregate([{
$project: {
_id: 0,
number: {
$let: {
vars: {
factor: {
$pow: [10, 3]
},
},
in: {
$let: {
vars: {
num: {$multiply: ["$$factor", "$number"]},
},
in: {
$switch: {
branches: [
{case: {$gte: ["$$num", {$add: [{$floor: "$$num"}, 0.5]}]}, then: {$divide:[ {$add: [{$floor: "$$num"}, 1.0]},"$$factor"]}},
{case: {$lt: ["$$num", {$add: [{$floor: "$$num"}, 0.5]}]}, then: {$divide:[{$floor: "$$num"}, "$$factor"]}}
]
}
}
}
}
}
}
}
}])
에 제컬션에다같음문있보가겠다라는 이름의 t
{ number" : 2.341567 }
{ number" : 2.0012 }
{ number" : 2.0012223 }
위의 쿼리를 실행한 결과 다음과 같은 메시지가 표시되었습니다.
{ "number" : 2.342 }
{ "number" : 2.001 }
{ "number" : 2.001 }
집계 관련 문제를 주의하십시오.작업할 때double
됩니다.type은 다음과 같이 됩니다.은됩반잘림올니다못때로때다니▁type▁incorrect▁sometimes됩▁round.다음은 예입니다.
5.885 --to double--> 5.8849999999999 ---$round(2)--> 5.88 (instead of 5.89)
다음은 해결 방법입니다.
> db.a.save({x:5.884})
> db.a.save({x:5.885})
> db.a.save({x:5.886})
> db.a.aggregate([{
$project:{
_id:0,
x: '$x',
round: {$round: ['$x', 2]}
better_round: {$round: [{$add: ['$x', 0.000000001]}, 2]}
}
}])
Output:
{ "x" : 5.884, "round" : 5.88, "better_round" : 5.88 }
{ "x" : 5.885, "round" : 5.88, "better_round" : 5.89 }
{ "x" : 5.886, "round" : 5.89, "better_round" : 5.89 }
언급URL : https://stackoverflow.com/questions/17482623/rounding-to-2-decimal-places-using-mongodb-aggregation-framework
'programing' 카테고리의 다른 글
Windows 7에서 명령 프롬프트에서 Python 프로그램을 실행하는 방법은 무엇입니까? (0) | 2023.07.07 |
---|---|
메모리 제한 초과로 인해 Firebase의 클라우드 기능이 중지되었습니다. (0) | 2023.07.07 |
압축된 파일을 Panda DataFrame으로 읽기 (0) | 2023.07.07 |
텍스트의 언어를 결정하는 방법은 무엇입니까? (0) | 2023.07.02 |
Python에서 지정된 URL에 매개 변수 추가 (0) | 2023.07.02 |