Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
F
fe-utils
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
sunguoshu
fe-utils
Commits
79b75073
Commit
79b75073
authored
Jul 17, 2023
by
sunguoshu
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/master'
parents
44748128
626c7e90
Pipeline
#320
canceled with stages
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
207 additions
and
53 deletions
+207
-53
numberToWords.ts
src/money/numberToWords.ts
+200
-53
numberToWords.test.ts
test/money/numberToWords.test.ts
+7
-0
No files found.
src/money/numberToWords.ts
View file @
79b75073
const
digits
=
[
'壹'
,
'贰'
,
'叁'
,
'肆'
,
'伍'
,
'陆'
,
'柒'
,
'捌'
,
'玖'
,
'零'
];
const
units
=
[
'拾'
,
'佰'
,
'仟'
,
'万'
,
'亿'
,
'兆'
,
];
const
units2
=
[
'角'
,
'分'
,
'厘'
,
'毫'
,
'丝'
];
export
default
function
numberToWords
(
input
:
string
|
number
):
string
{
input
=
String
(
input
)
let
newInput
if
(
input
===
undefined
||
input
===
null
||
input
===
''
||
!
/^
[\-]?\d{0,21}(\.\d{0,3})?
$/
.
test
(
input
))
{
return
input
;
const
digits
=
[
'壹'
,
'贰'
,
'叁'
,
'肆'
,
'伍'
,
'陆'
,
'柒'
,
'捌'
,
'玖'
,
'零'
]
const
units
=
[
'拾'
,
'佰'
,
'仟'
,
'万'
,
'亿'
,
'兆'
]
const
units2
=
[
'角'
,
'分'
,
'厘'
,
'毫'
,
'丝'
]
const
maxlength
=
16
function
isDefined
(
value
)
{
return
typeof
value
!==
'undefined'
}
function
isEmpty
(
val
)
{
// null or undefined
if
(
val
==
null
)
return
true
if
(
typeof
val
===
'boolean'
)
return
false
if
(
val
===
0
)
return
false
if
(
typeof
val
===
'number'
)
return
!
val
if
(
val
instanceof
Error
)
return
val
.
message
===
''
switch
(
Object
.
prototype
.
toString
.
call
(
val
))
{
// String or Array
case
'[object String]'
:
case
'[object Array]'
:
return
!
val
.
length
// Map or Set or File
case
'[object File]'
:
case
'[object Map]'
:
case
'[object Set]'
:
{
return
!
val
.
size
}
// Plain Object
case
'[object Object]'
:
{
return
!
Object
.
keys
(
val
).
length
}
}
if
(
/
[\-]\d{0,21}(\.\d{0,3})?
$/
.
test
(
input
)){
newInput
=
input
.
replace
(
/-/
,
""
);
}
else
{
newInput
=
input
;
return
false
}
function
toStdAmount
(
sAmount
)
{
if
(
!
isDefined
(
sAmount
)
||
isEmpty
(
sAmount
))
return
// if (sAmount.indexOf('-') >= 0) {
// 替换掉负号
var
rFlag
=
sAmount
.
indexOf
(
'-'
)
>=
0
sAmount
=
sAmount
.
replace
(
/-/g
,
''
)
// }
var
sComma
=
/
\,
/gi
var
sResult
=
sAmount
.
replace
(
sComma
,
''
)
var
iDotIndex
=
sResult
.
indexOf
(
'.'
)
var
iLength
=
sResult
.
length
var
toMatchNaNum
=
/
\D
/
var
flag
=
true
if
(
(
iDotIndex
!=
-
1
&&
(
iLength
-
iDotIndex
>
3
||
toMatchNaNum
.
test
(
sResult
.
slice
(
0
,
iDotIndex
))))
||
toMatchNaNum
.
test
(
sResult
.
slice
(
iDotIndex
+
1
,
iLength
))
)
{
flag
=
false
return
sResult
.
substr
(
0
,
iDotIndex
+
3
)
// 小数点后大于2位数 或 含有非数字字符
}
else
{
// 将金额处理为######.##形式
if
(
iDotIndex
==
-
1
)
{
sResult
=
sResult
+
'.00'
}
else
if
(
iDotIndex
==
0
)
{
if
(
iLength
-
iDotIndex
==
1
)
sResult
=
'0'
+
sResult
+
'00'
if
(
iLength
-
iDotIndex
==
2
)
sResult
=
'0'
+
sResult
+
'0'
if
(
iLength
-
iDotIndex
==
3
)
sResult
=
'0'
+
sResult
}
else
{
if
(
iLength
-
iDotIndex
==
2
)
sResult
=
sResult
+
'0'
if
(
iLength
-
iDotIndex
==
1
)
sResult
=
sResult
+
'00'
}
// 处理金额非前面的0
var
sTemp
=
''
sTemp
=
sResult
.
slice
(
0
,
iDotIndex
)
var
iTemp
=
new
Number
(
sTemp
)
sTemp
=
iTemp
.
toString
()
if
(
sTemp
.
length
>
maxlength
)
{
flag
=
false
return
null
// 太长的金额
}
iDotIndex
=
sResult
.
indexOf
(
'.'
)
sResult
=
sTemp
+
sResult
.
slice
(
iDotIndex
)
// 返回######.##形式的金额
return
rFlag
?
'-'
+
sResult
:
sResult
}
newInput
=
newInput
.
replace
(
/^0+$/
,
"0"
).
replace
(
/^0+
([
1-9
]
.*
)
/
,
"$1"
);
const
CN1
=
[
'零'
,
'壹'
,
'贰'
,
'叁'
,
'肆'
,
'伍'
,
'陆'
,
'柒'
,
'捌'
,
'玖'
];
const
CN2
=
[
'元'
,
'万'
,
'亿'
,
'兆'
,
'京'
,
'垓'
];
const
CN3
=
[
''
,
'拾'
,
'佰'
,
'仟'
];
const
CN4
=
[
'角'
,
'分'
,
'厘'
];
newInput
=
newInput
+
""
;
const
arr
=
newInput
.
split
(
"."
);
let
int
=
arr
[
0
],
dot
=
arr
[
1
];
//分成整数和小数两个部分
let
intArr
=
int
.
split
(
""
);
let
counter
=
0
;
for
(
let
i
=
intArr
.
length
-
1
;
i
>=
0
;
i
--
)
{
intArr
[
i
]
=
CN1
[
intArr
[
i
]]
+
CN3
[
counter
%
4
];
if
(
counter
%
4
==
0
)
{
intArr
[
i
]
+=
CN2
[
counter
/
4
];
}
export
default
function
numberToWords
(
sAmount
:
string
|
number
):
string
|
boolean
{
sAmount
=
sAmount
+
''
var
rFlag
=
sAmount
.
indexOf
(
'-'
)
>=
0
sAmount
=
sAmount
.
replace
(
/-/g
,
''
).
replace
(
/
[^\d\.\-]
+/g
,
''
)
var
value
=
toStdAmount
(
sAmount
)
if
(
value
.
indexOf
(
'.'
)
!=
value
.
lastIndexOf
(
'.'
))
return
'金额输入有误'
var
sCN_Num
=
new
Array
(
'零'
,
'壹'
,
'贰'
,
'叁'
,
'肆'
,
'伍'
,
'陆'
,
'柒'
,
'捌'
,
'玖'
)
var
unit
=
new
Array
(
'元'
,
'万'
,
'亿'
,
'万'
)
var
subunit
=
new
Array
(
'拾'
,
'佰'
,
'仟'
)
var
sCNzero
=
'零'
var
result
=
''
var
iDotIndex
=
value
.
indexOf
(
'.'
)
var
sBeforeDot
=
value
.
slice
(
0
,
iDotIndex
)
var
sAfterDot
=
value
.
slice
(
iDotIndex
)
var
len
=
0
len
=
sBeforeDot
.
length
var
i
=
0
,
j
=
0
,
k
=
0
// j is use to subunit,k is use to unit
var
oldC
=
'3'
var
cc
=
'0'
result
=
unit
[
0
]
+
result
var
oldHasN
=
false
var
hasN
=
false
var
allZero
=
true
for
(
var
i
=
0
;
i
<
len
;
i
++
)
{
if
(
j
==
0
&&
i
!=
0
)
{
if
(
!
hasN
)
{
if
(
k
%
2
==
0
)
result
=
result
.
slice
(
1
)
}
else
{
if
(
oldC
==
'0'
)
result
=
sCNzero
+
result
}
counter
++
;
}
int
=
intArr
.
join
(
""
).
replace
(
/
(
零仟|零佰|零拾
)
/g
,
"零"
).
replace
(
/零+/g
,
"零"
).
replace
(
/零
(
元|万|亿|兆|京|垓
)
/g
,
"$1"
).
replace
(
/亿万/
,
"亿"
).
replace
(
/兆亿/
,
"兆"
).
replace
(
/京兆/
,
"京"
).
replace
(
/垓京/
,
"垓"
);
if
(
int
===
'元'
)
{
int
=
'零元'
;
if
(
oldC
==
'0'
&&
result
[
0
]
!==
'零'
&&
result
[
0
]
!==
'元'
)
{
result
=
'零'
+
result
}
result
=
unit
[
k
]
+
result
oldHasN
=
hasN
hasN
=
false
}
cc
=
sBeforeDot
.
charAt
(
len
-
i
-
1
)
if
(
oldC
==
'0'
&&
cc
!=
oldC
)
{
if
(
hasN
)
result
=
sCNzero
+
result
}
if
(
cc
!=
'0'
)
{
if
(
j
!=
0
)
{
result
=
subunit
[
j
-
1
]
+
result
}
var
dig
=
'0'
dig
=
sCN_Num
[
cc
]
if
(
dig
==
'0'
)
{
return
false
}
hasN
=
true
allZero
=
false
result
=
dig
+
result
}
oldC
=
cc
j
++
if
(
j
==
4
)
{
k
++
j
=
0
}
}
if
(
!
dot
||
/^0+$/
.
test
(
dot
))
{
if
(
/^
[\-]\d{0,21}(\.\d{0,3})?
$/
.
test
(
input
)){
let
value
=
input
.
length
==
1
?
"负"
:
"负"
+
int
+
"整"
return
value
;
}
else
{
return
int
+
"整"
;
if
(
allZero
)
{
result
=
'零元'
}
else
{
var
bb
=
0
if
(
!
hasN
)
{
bb
++
if
(
!
oldHasN
)
{
bb
++
}
}
if
(
bb
!=
0
)
{
result
=
result
.
slice
(
bb
)
}
if
(
result
.
charAt
(
0
)
==
'零'
)
{
result
=
result
.
slice
(
1
)
}
}
// after dot
sAfterDot
=
sAfterDot
.
slice
(
1
)
len
=
sAfterDot
.
length
var
corn
=
new
Array
(
'0'
,
'0'
)
var
cornunit
=
new
Array
(
'角'
,
'分'
)
var
n
=
0
// j is use to subunit,k is use to unit
var
dig
=
'0'
corn
[
0
]
=
sAfterDot
.
charAt
(
0
)
if
(
len
>
1
)
{
corn
[
1
]
=
sAfterDot
.
charAt
(
1
)
}
else
{
corn
[
1
]
=
'0'
}
if
(
corn
[
0
]
==
'0'
&&
corn
[
1
]
==
'0'
)
{
return
rFlag
?
(
result
=
'-'
+
result
+
'整'
)
:
(
result
+=
'整'
)
}
else
{
dot
=
dot
.
split
(
""
).
map
(
function
(
item
,
index
)
{
return
CN1
[
item
]
+
CN4
[
index
];
}).
join
(
""
);
dot
=
dot
.
replace
(
/
(
零角|零分|零厘
)
/g
,
"零"
).
replace
(
/零+/g
,
"零"
).
replace
(
/零$/
,
""
);
if
(
/^
[\-]\d{0,21}(\.\d{0,3})?
$/
.
test
(
input
)){
return
"负"
+
int
+
dot
;
}
else
{
return
int
+
dot
;
if
(
allZero
)
result
=
''
}
for
(
var
i
=
0
;
i
<
2
;
i
++
)
{
var
curchar
=
corn
[
i
]
dig
=
sCN_Num
[
curchar
]
if
(
i
==
0
)
{
if
(
result
!=
''
||
curchar
!=
'0'
)
{
result
+=
dig
}
if
(
curchar
!=
'0'
)
{
result
+=
cornunit
[
0
]
}
}
if
(
i
==
1
&&
curchar
!=
'0'
)
{
result
=
result
+
dig
+
cornunit
[
1
]
}
}
}
\ No newline at end of file
return
rFlag
?
'负 '
+
result
:
result
}
test/money/numberToWords.test.ts
View file @
79b75073
...
...
@@ -2,6 +2,13 @@ import { describe, it, expect } from 'vitest'
import
numberToWords
from
'../../src/money/numberToWords'
describe
(
'测试整数'
,
()
=>
{
it
(
'17916.67 toBe 壹万柒仟玖佰壹拾陆元陆角柒分'
,
()
=>
{
expect
(
numberToWords
(
17916.67
)).
toBe
(
'壹万柒仟玖佰壹拾陆元陆角柒分'
)
})
it
(
'12500.06 toBe 壹万贰仟伍佰元零陆分'
,
()
=>
{
expect
(
numberToWords
(
12500.06
)).
toBe
(
'壹万贰仟伍佰元零陆分'
)
})
it
(
'1 toBe 壹元整'
,
()
=>
{
expect
(
numberToWords
(
1
)).
toBe
(
'壹元整'
)
})
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment