注册 登录
编程论坛 VFP论坛

求:一个好像很简单的问题,愣是想不到一个很简单的算法?

cssnet 发布于 2023-03-11 12:57, 4891 次点击
设:
有8个字符型字段,A1...A8 (C) 12——
A1、A2、A3、A4、A5、A6、A7、A8
它们的值,有可能相同,也有可能不同,例如:
A1 ="七仙女"
A2 ="黄大仙"
A3 ="黄大仙"
A4 ="黄大仙"
A5 ="黄小仙"
A6 ="黄大仙"
A7 ="黄大仙"
A8 ="王母娘娘"
求:
如何迅速计算出8个字段的“重合率”,并将结果填入A9字段。
比如上例,A9 = 5/8 = 0.625(即62.5%)
43 回复
#2
sdta2023-03-11 13:15
如果有多个字段有重合,如何将结果保存A9中
A1 ="七仙女"
A2 ="黄大仙"
A3 ="黄大仙"
A4 ="黄大仙"
A5 ="七仙女"
A6 ="黄大仙"
A7 ="黄大仙"
A8 ="王母娘娘"
OCCURS()应该有用处吧

[此贴子已经被作者于2023-3-11 15:56编辑过]

#3
cssnet2023-03-11 14:11
以下是引用sdta在2023-3-11 13:15:44的发言:
OCCURS()应该有用处吧


高!一语点醒梦中人啊!
#4
sam_jiang2023-03-11 15:45
#5
cssnet2023-03-13 11:50
以下是引用sdta在2023-3-11 13:15:44的发言:
如果有多个字段有重合,OCCURS()应该有用处吧


能想到的初步算法是:

lnMaxRate = 0
lcMaxA = ""
lcAll_A = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8    &&A1...A8有效字符不超过10位,而字段宽度预设为12,右边皆有空格

lcA  = A1
lnRate = OCCURS(lcA, lcAll_A)
if lnRate > lnMaxRate
    lcMaxA = lcA
    lnMaxRate = lnRate
endif

lcA  = A2
lnRate = OCCURS(lcA, lcAll_A)
if lnRate > lnMaxRate
    lcMaxA = lcA
    lnMaxRate = lnRate
endif

lcA  = A3
lnRate = OCCURS(lcA, lcAll_A)
if lnRate > lnMaxRate
    lcMaxA = lcA
    lnMaxRate = lnRate
endif

...

replace A9 with lnMaxRate, MaxA with lcMaxA

==================

不知有无更简洁的算法?
#6
吹水佬2023-03-13 12:39
搞成这样可否
只有本站会员才能查看附件,请 登录
#7
csyx2023-03-13 14:56
Create Cursor test ( ;
     a1 V(10),a2 V(10),a3 V(10),a4 V(10),a5 V(10),a6 V(10),a7 V(10),a8 V(10) ;
     ,rate Y,maxa V(10))
Insert into test (a1,a2,a3,a4,a5,a6,a7,a8) values ( ;
    "七仙女","黄大仙","黄大仙","黄大仙","黄小仙","黄大仙","黄大仙","王母娘娘")
Insert into test (a1,a2,a3,a4,a5,a6,a7,a8) values ( ;
    "七仙女","黄大仙","七仙女","黄大仙","七仙女","七仙女","黄小仙","王母娘娘")

Select test
Scan all
    Release aaa,bbb
    nn = Recno()
    Copy To array aaa fields like 'a?' RECORD nn
    Dimension aaa[Alen(aaa,2),1]
    Create Cursor temp (ax V(10))
    Append From array aaa
    Select ax, Count(*) from temp group by ax order by 2 desc into array bbb
    Use in temp
    Select test
    Replace next 1 maxa with bbb[1,1], rate with bbb[1,2] / Alen(aaa,1)
EndScan
Browse
#8
sdta2023-03-13 15:10
细节楼主没说清楚(2楼的情况如何处理,多个值有重复内容)
#9
cssnet2023-03-13 15:23
以下是引用sdta在2023-3-13 15:10:53的发言:
细节楼主没说清楚(2楼的情况如何处理,多个值有重复内容)


感谢关注!
这个算法,目的就是获取在8个字段当中,重复次数最多的一个重复项,以及此重复项的重复率。
多个值有重复内容,取重复次数最多的那一个值。
#10
cssnet2023-03-13 15:34
以下是引用csyx在2023-3-13 14:56:09的发言:

Create Cursor test ( ;
     a1 V(10),a2 V(10),a3 V(10),a4 V(10),a5 V(10),a6 V(10),a7 V(10),a8 V(10) ;
     ,rate Y,maxa V(10))
Insert into test (a1,a2,a3,a4,a5,a6,a7,a8) values ( ;
    "七仙女","黄大仙","黄大仙","黄大仙","黄小仙","黄大仙","黄大仙","王母娘娘")
Insert into test (a1,a2,a3,a4,a5,a6,a7,a8) values ( ;
    "七仙女","黄大仙","七仙女","黄大仙","七仙女","七仙女","黄小仙","王母娘娘")
Insert into test (a1,a2,a3,a4,a5,a6,a7,a8) values ( ;
    "黄小仙","黄大仙","黄小仙","黄大仙","黄小仙","七仙女","黄小仙","王母娘娘")
Insert into test (a1,a2,a3,a4,a5,a6,a7,a8) values ( ;
    "王母娘娘","王母娘娘","黄大仙","黄大仙","黄小仙","王母娘娘","王母娘娘","王母娘娘")

Select test
Scan all
    Release aaa,bbb
    nn = Recno()
    Copy To array aaa fields like 'a?' RECORD nn
    Dimension aaa[Alen(aaa,2),1]
    Create Cursor temp (ax V(10))
    Append From array aaa
    Select ax, Count(*) from temp group by ax order by 2 desc into array bbb
    Use in temp
    Select test
    Replace next 1 maxa with bbb[1,1], rate with bbb[1,2] / Alen(aaa,1)
EndScan
Browse



这个算法非常简洁!
远比我写的那一大堆啰哩啰嗦的8次机械比较算法,简洁了不知多少倍!
就是有些艰涩,我得逐句逐句好好消化一下子。
#11
csyx2023-03-13 15:54
也没啥好晦涩的
1. copy to array aaa ...  复制某一行几个字段的值到一数组,这里偷懒写成 fields like 'a?',若实际字段名无规律,改成完成的字段名列表,多打些字母而已
2. dimension aaa[...]  相当于行转列,以便后面用 append from array 将数据附加到临时表 temp 的 ax 字段中
最后交给 sql-select 统计每个值的出现次数,这些好像也不用解释了

当然,如果数据是:【王母,大姐,二姐,三姐,四姐,五姐,六姐,七妹】我不知谁该排第一
或者:【张三,李四,王五,赵六,张三,李四,王五,赵六】谁又该排第一

[此贴子已经被作者于2023-3-13 16:04编辑过]

#12
sdta2023-03-13 16:31
以下是引用csyx在2023-3-13 15:54:27的发言:

也没啥好晦涩的
1. copy to array aaa ...  复制某一行几个字段的值到一数组,这里偷懒写成 fields like 'a?',若实际字段名无规律,改成完成的字段名列表,多打些字母而已
2. dimension aaa[...]  相当于行转列,以便后面用 append from array 将数据附加到临时表 temp 的 ax 字段中
最后交给 sql-select 统计每个值的出现次数,这些好像也不用解释了

当然,如果数据是:【王母,大姐,二姐,三姐,四姐,五姐,六姐,七妹】我不知谁该排第一
或者:【张三,李四,王五,赵六,张三,李四,王五,赵六】谁又该排第一

算法规则问题没说清楚
#13
cssnet2023-03-13 16:45
以下是引用csyx在2023-3-13 15:54:27的发言:

2. dimension aaa[...]  相当于行转列


哈哈哈哈,就是“行转列”,我一时转不过弯来!
数据拿到手时,我一直就没想清楚:这个……列数据如何group by?结果一直就陷在这死胡同里出不来啦。

非常感谢!
#14
cssnet2023-03-13 17:19
以下是引用csyx在2023-3-13 15:54:27的发言:

如果数据是:【王母,大姐,二姐,三姐,四姐,五姐,六姐,七妹】我不知谁该排第一
或者:【张三,李四,王五,赵六,张三,李四,王五,赵六】谁又该排第一


这个无所谓,只需找出第一个第一,并列第一者就忽略呗,反正不违背初衷:
找出最大次数的重复者,并统计重复率。
#15
sam_jiang2023-03-13 20:41
CLEAR
Create Cursor test ( ;
     a1 V(10),a2 V(10),a3 V(10),a4 V(10),a5 V(10),a6 V(10),a7 V(10),a8 V(10) ;
     ,rate Y,maxa V(10))
Insert into test (a1,a2,a3,a4,a5,a6,a7,a8) values ( ;
    "七仙女","黄大仙","黄大仙","黄大仙","黄小仙","黄大仙","黄大仙","王母娘娘")
Insert into test (a1,a2,a3,a4,a5,a6,a7,a8) values ( ;
    "七仙女","黄大仙","七仙女","黄大仙","七仙女","七仙女","黄小仙","王母娘娘")
Insert into test (a1,a2,a3,a4,a5,a6,a7,a8) values ( ;
    "黄小仙","黄大仙","黄小仙","黄大仙","黄小仙","七仙女","黄小仙","王母娘娘")
Insert into test (a1,a2,a3,a4,a5,a6,a7,a8) values ( ;
    "王母娘娘","王母娘娘","黄大仙","黄大仙","黄小仙","王母娘娘","王母娘娘","王母娘娘")
GO top
FOR n=1 TO RECCOUNT()
    SCATTER FIELDS a1,a2,a3,a4,a5,a6,a7,a8 TO array1
    ctext=""
    FOR i=1 TO 8
        ctext=ctext+array1(i)
    ENDFOR
    nmaxtimes=0
    FOR i=1 TO 8
        ntimes=OCCURS(array1(i),ctext)
        nmaxtimes=MAX(nmaxtimes,ntimes)
    ENDF
    i=0
    DO WHILE .t.
        IF i>8
            EXIT
        ELSE
            i=i+1   
            ntimes=OCCURS(array1(i),ctext)
            IF ntimes=nmaxtimes
                REPLACE rate WITH (nmaxtimes/8)
                REPLACE maxa WITH array1(i)
                EXIT
            ELSE
                LOOP
            ENDIF
        ENDIF
    ENDDO
    SKIP     
ENDFOR
LIST
#16
cssnet2023-03-13 21:30
非常感谢sam_jiang和诸位网友的帮助!

玩大一点点,为这算法增加一点点通用性或难度:

假设:
A1...A18
皆为整型数值字段
求:
获取重复次数最多的一个字段值,及其重复次数。

这一回,若打算再勉强用OCCURS(),恐怕就必须先Str(),然后才能OCCURS()啦。
不知还有没有能上天入地的奇门遁甲法门?

#17
吹水佬2023-03-13 23:14
以下是引用cssnet在2023-3-13 21:30:08的发言:

非常感谢sam_jiang和诸位网友的帮助!

玩大一点点,为这算法增加一点点通用性或难度:

假设:
A1...A18
皆为整型数值字段
求:
获取重复次数最多的一个字段值,及其重复次数。

这一回,若打算再勉强用OCCURS(),恐怕就必须先Str(),然后才能OCCURS()啦。
不知还有没有能上天入地的奇门遁甲法门?

条件好像不够充分?
18个字段 ..... 最多的一个字段值,这“18个”与“一个”是什么关系。
试举例说明

[此贴子已经被作者于2023-3-13 23:15编辑过]

#18
cssnet2023-03-13 23:27
以下是引用吹水佬在2023-3-13 23:14:22的发言:

条件好像不够充分?
18个字段 ..... 最多的一个字段值,这“18个”与“一个”是什么关系。
试举例说明


哈哈哈哈,纯属信口胡诌的,说得也不严谨。
例如,假设一行记录是一位学生各科的分数:
98,95,74,92,65,92,92,77,92,88,92,……
统计当中出现最多的一个分数值,以及出现的次数。
上例可能是:92,5次。

#19
吹水佬2023-03-14 05:25
以下是引用cssnet在2023-3-13 23:27:01的发言:

哈哈哈哈,纯属信口胡诌的,说得也不严谨。
例如,假设一行记录是一位学生各科的分数:
98,95,74,92,65,92,92,77,92,88,92,……
统计当中出现最多的一个分数值,以及出现的次数。
上例可能是:92,5次。

这的意思与我在6楼给的结果不是一样吗?
这与字段多少无关,明显就是一个数据分类统计的问题。
如果数据较复杂和数据量大,数据结构再能优化一下,统计算法应该可以更简单些,不用倒来倒去。
#20
吹水佬2023-03-14 05:35
以下是引用cssnet在2023-3-13 23:27:01的发言:
例如,假设一行记录是一位学生各科的分数:
98,95,74,92,65,92,92,77,92,88,92,……
统计当中出现最多的一个分数值,以及出现的次数。
上例可能是:92,5次。

只是分类统计分数值,可以直接用数组统计,简单快速。
#21
csyx2023-03-14 07:20
以下是引用cssnet在2023-3-13 21:30:08的发言:

非常感谢sam_jiang和诸位网友的帮助!

玩大一点点,为这算法增加一点点通用性或难度:

假设:
A1...A18
皆为整型数值字段
求:
获取重复次数最多的一个字段值,及其重复次数。

看不出有多大不同,算法逻辑还一样。或者我对需求理解有误?小小改动一下就行,关键还是行转列那句
Create Cursor test (最高分 I, 次数 I ;
    ,a1 I,a2 I,a3 I,a4 I,a5 I,a6 I,a7 I,a8 I,a9 I ;
    ,a10 I,a11 I,a12 I,a13 I,a14 I,a15 I,a16 I,a17 I,a18 I ;
)
Insert into test (a1,a2,a3,a4,a5,a6,a7,a8,a9 ;
    ,a10,a11,a12,a13,a14,a15,a16,a17,a18) Values ( ;
        1,2,3, 4,5,6, 7,8,9, 2,3,4, 5,6,7, 10,9,9)
Insert into test (a1,a2,a3,a4,a5,a6,a7,a8,a9 ;
    ,a10,a11,a12,a13,a14,a15,a16,a17,a18) Values ( ;
        98,95,74, 92,65,92, 92,77,92 ;
        ,88,92,87, 18,15,14, 22,25,22)

Select test
Scan all
    Dimension aaa[1]
    Scatter to aaa FIELDS like a*
    Dimension aaa[Alen(aaa),1]
    Create Cursor temp (ax I)
    Append From array aaa
    Select top 1 ax, Count(*) from temp group by ax order by 2 desc into array aaa
    Use in temp
    Replace next 1 最高分 with aaa[1], 次数 with aaa[2] in test
EndScan
Browse

[此贴子已经被作者于2023-3-14 07:21编辑过]

#22
cssnet2023-03-14 09:17
以下是引用csyx在2023-3-14 07:20:08的发言:
看不出有多大不同,算法逻辑还一样。


感谢csyx、吹版的关注!
其实,我突发奇想将数据类型改为整型值,重点在于挑战OCCURS()。
在此,我毫不掩饰对于OCCURS()的偏爱。
事关,此函数若用OCCURS()来实现,那么,代码哪怕放到几十年后阅读,仍然无需注释秒懂,因逻辑简单,一目了然。
然而,整型值无法直接OCCURS(),用str()转换,最大长度为11字节,效率上难免大打折扣!

当然,可能有其他奇技淫巧,能够缩减字节数。比方说:
N1=1314520520
C1=TRANSFORM(N1,"@0")
C1=right(C1,8)
这样能将长度变为8字节。

此外,还有更变态的,只可惜VFP似乎遇到0xFFFF的字符会越界出错:
N1=0xFFFFFFFF
NL = BitRshift(N1,16)
NR = BitAnd(N1, 0xFFFF)
CL = chr(NL)
CR = chr(NR)
当数值为0xFFFF(十进制值65535)时,我过不了chr()这一关,无法构造出内码值为0xFFFF的字符串来,这一点比较遗憾。
退而求其次,这么弄:
Nsrc=0xFFFFFFFF
N1 = BitRshift(Nsrc,24)
N2 = BitAnd(BitRshift(Nsrc,16), 0xFF)
N3 = BitAnd(BitRshift(Nsrc,8), 0xFF)
N4 = BitAnd(Nsrc, 0xFF)
N2C = chr(N1)+chr(N2)+chr(N3)+chr(N4)
现在,N2C就是四字节的由整型值内码构造出来的字符串了。

那么,OCCURS()或许仍是值得依赖的。


[此贴子已经被作者于2023-3-14 11:17编辑过]

#23
吹水佬2023-03-14 09:58
回复 22楼 cssnet
VFP对整数的表达方式有内码和外码之分。
内码是32bit,转换用BINTOC()、CTOBIN(),数值范围-2147483648~2147483647 (内码0x0~0xFFFFFFFF)
外码通常以字符串方式表达,可精确到(+/-)16位数字。
#24
csyx2023-03-14 10:14
分组统计本来就是 SQL 的强项,且 SQL 语句就像说英语一样带有自说明性,通用且容易理解
我的习惯是遇到需要统计的时候尽量用 SQL 语句解决
#25
cssnet2023-03-14 10:49
以下是引用吹水佬在2023-3-14 09:58:38的发言:
内码是32bit,转换用BINTOC()、CTOBIN(),数值范围-2147483648~2147483647 (内码0x0~0xFFFFFFFF)


对!就是bintoc()!我随手构造N1...N4,就是因为一时忘了这个函数(其实平常经常用到的),呵呵呵呵。

N1 = 1314520520
C1 = bintoc(N1, "4RS")

如此,C1 = 0h4E59FDC8,那么就可以像occu(子字符串, 大字符串)一样地occu(整型值内码字符串, 大字符串)啦!

#26
吹水佬2023-03-14 11:03
以下是引用cssnet在2023-3-14 10:49:47的发言:
N1 = 1314520520
C1 = bintoc(N1, "4RS")

bintoc好像是针对有符号整数,试试:
N1 = 0x80000000
C1 = bintoc(N1, "4RS")
如果要处理无符号整数,就要转换一下:
C1 = bintoc(N1-2^32, "4RS")
#27
cssnet2023-03-14 11:16
以下是引用吹水佬在2023-3-14 11:03:28的发言:
bintoc好像是针对有符号整数


其实有符号或无符号,似乎不太关键,
事关,bintoc()和ctobin()配对,
无论中间过程的值在VFP内部如何处理,最终总能被ctobin()正确还原。
而且在此只是借用整型数的内码值,临时用作了字符串;
具体中间过程的实现细节,权当作透明,直接忽略即可。
事实上,倘若仔细验证过occu()函数运行起来准确无误的话,
直接C1=bintoc(N1)即可,也不必附加标志参数"4RS"。
#28
吹水佬2023-03-14 11:23
以下是引用cssnet在2023-3-14 11:16:28的发言:



其实有符号或无符号,似乎不太关键,

不到你“不太关键”,除非你处理的数据小于0x80000000,否则,直接 bintoc(0x80000000, "4RS") 是行不通的。
#29
sam_jiang2023-03-14 12:36
你对occurs是不是有什么误解,这是个字符串函数。

借用楼上那位兄弟的数据用一下。

clea
Create Cursor test ( ;
    a1 I,a2 I,a3 I,a4 I,a5 I,a6 I,a7 I,a8 I,a9 I ;
    ,a10 I,a11 I,a12 I,a13 I,a14 I,a15 I,a16 I,a17 I,a18 I ,score I, count I;
)
Insert into test (a1,a2,a3,a4,a5,a6,a7,a8,a9 ;
    ,a10,a11,a12,a13,a14,a15,a16,a17,a18) Values ( ;
        1,2,3, 4,5,6, 7,8,9, 2,3,4, 5,6,7, 10,9,9)
Insert into test (a1,a2,a3,a4,a5,a6,a7,a8,a9 ;
    ,a10,a11,a12,a13,a14,a15,a16,a17,a18) Values ( ;
        98,95,74, 92,65,92, 92,77,92 ;
        ,88,92,87, 18,15,14, 22,25,22)
GO top
FOR i=1 TO RECCOUNT()
    SCATTER FIELDS a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18 TO array1
    ntimes=0
    FOR j=1 TO ALEN(array1)
        n=acount(@array1,array1(j))
        IF n>ntimes
            nvalue=array1(j)
        ENDIF
        ntimes=MAX(ntimes,n)
    ENDFOR
    REPLACE score WITH nvalue,count WITH ntimes
    SKIP
ENDFOR
BROWSE

FUNCTION acount
PARAMETERS carray,nnum
LOCAL i
ncount=0
FOR i=1 TO ALEN(carray)
    IF carray(i)=nnum
        ncount=ncount+1
    ENDIF
ENDFOR
RETURN ncount
ENDFUNC
#30
sam_jiang2023-03-14 13:01
两段代码基本上可以通用:

clea
*!*    Create Cursor test ( ;
*!*        a1 I,a2 I,a3 I,a4 I,a5 I,a6 I,a7 I,a8 I,a9 I ;
*!*        ,a10 I,a11 I,a12 I,a13 I,a14 I,a15 I,a16 I,a17 I,a18 I ,score I, count I;
*!*    )
*!*    Insert into test (a1,a2,a3,a4,a5,a6,a7,a8,a9 ;
*!*        ,a10,a11,a12,a13,a14,a15,a16,a17,a18) Values ( ;
*!*            1,2,3, 4,5,6, 7,8,9, 2,3,4, 5,6,7, 10,9,9)
*!*    Insert into test (a1,a2,a3,a4,a5,a6,a7,a8,a9 ;
*!*        ,a10,a11,a12,a13,a14,a15,a16,a17,a18) Values ( ;
*!*            98,95,74, 92,65,92, 92,77,92 ;
*!*            ,88,92,87, 18,15,14, 22,25,22)
Create Cursor test ( ;
     a1 V(10),a2 V(10),a3 V(10),a4 V(10),a5 V(10),a6 V(10),a7 V(10),a8 V(10) ;
     ,rate Y,maxa V(10))
Insert into test (a1,a2,a3,a4,a5,a6,a7,a8) values ( ;
    "七仙女","黄大仙","黄大仙","黄大仙","黄小仙","黄大仙","黄大仙","王母娘娘")
Insert into test (a1,a2,a3,a4,a5,a6,a7,a8) values ( ;
    "七仙女","黄大仙","七仙女","黄大仙","七仙女","七仙女","黄小仙","王母娘娘")
Insert into test (a1,a2,a3,a4,a5,a6,a7,a8) values ( ;
    "黄小仙","黄大仙","黄小仙","黄大仙","黄小仙","七仙女","黄小仙","王母娘娘")
Insert into test (a1,a2,a3,a4,a5,a6,a7,a8) values ( ;
    "王母娘娘","王母娘娘","黄大仙","黄大仙","黄小仙","王母娘娘","王母娘娘","王母娘娘")

GO top
FOR i=1 TO RECCOUNT()
        SCATTER FIELDS LIKE a* TO array1
    ntimes=0
    FOR j=1 TO ALEN(array1)
        n=acount(@array1,array1(j))
        IF n>ntimes
            nvalue=array1(j)
        ENDIF
        ntimes=MAX(ntimes,n)
    ENDFOR
*!*        REPLACE score WITH nvalue,count WITH ntimes
        REPLACE rate WITH ntimes/8,maxa WITH nvalue
    SKIP
ENDFOR
BROWSE

FUNCTION acount
PARAMETERS carray,evalue
LOCAL i
ncount=0
FOR i=1 TO ALEN(carray)
    IF carray(i)=evalue
        ncount=ncount+1
    ENDIF
ENDFOR
RETURN ncount
ENDFUNC
#31
cssnet2023-03-14 13:22
以下是引用sam_jiang在2023-3-14 12:36:20的发言:

你对occurs是不是有什么误解,这是个字符串函数。


您误解啦。我后边探讨的,正是尝试用类似occurs()这样的字符串函数,去处理整型值数据。
只因某些字符串函数,在处理某些情况下的查询统计时,会比较简单、方便,而数值函数却没有这种便利。
#32
cssnet2023-03-14 13:28
以下是引用吹水佬在2023-3-14 11:23:22的发言:
不到你“不太关键”,除非你处理的数据小于0x80000000,否则,直接 bintoc(0x80000000, "4RS") 是行不通的。


明白啦!bintoc()第一个参数是有符号整数,它只能接受小于0x80000000正数值,因最高位是符号位。
那么说来,我手动构造4字节无符号整数,反倒是有点用处的。

#33
吹水佬2023-03-14 13:48
以下是引用cssnet在2023-3-14 13:28:21的发言:

明白啦!bintoc()第一个参数是有符号整数,它只能接受小于0x80000000正数值,因最高位是符号位。
那么说来,我手动构造4字节无符号整数,反倒是有点用处的。

看来26楼说的还没注意到
#34
cssnet2023-03-14 14:36
以下是引用吹水佬在2023-3-14 13:48:31的发言:
看来26楼说的还没注意到


其实,我针对的是VFP可正确处理的整型数值,或者说,数据类型为“I”的字段值。
只要VFP能正确处理这个数值,那么bintoc()处理起来,应无问题…………难道不是吗?
现在,字符串函数要用到的,正是bintoc(某I值),理论上,不会溢出。
#35
吹水佬2023-03-14 15:52
以下是引用cssnet在2023-3-14 14:36:01的发言:



其实,我针对的是VFP可正确处理的整型数值,或者说,数据类型为“I”的字段值。
只要VFP能正确处理这个数值,那么bintoc()处理起来,应无问题…………难道不是吗?
现在,字符串函数要用到的,正是bintoc(某I值),理论上,不会溢出。

DBF的I型数据本身是按内码存放的,不用再转换来转换去,将DBF当作字符来处理就可以。
继续绕
#36
cssnet2023-03-14 16:04
以下是引用吹水佬在2023-3-14 15:52:40的发言:
DBF的I型数据本身是按内码存放的,不用再转换来转换去,将DBF当作字符来处理就可以。
继续绕


关键是,字符串函数,它不接受数值型参数哇!
话说,脱裤子放P,有时候,绝对是有必要的;
绕,其目的是让这一督P,放将出去后,合规合矩,师出有名。
绕,其本身不是目的,而只是合规所须经历的必要手段。
#37
吹水佬2023-03-14 16:22
以下是引用cssnet在2023-3-14 16:04:47的发言:



关键是,字符串函数,它不接受数值型参数哇!
话说,脱裤子放P,有时候,绝对是有必要的;
绕,其目的是让这一督P,放将出去后,合规合矩,师出有名。
绕,其本身不是目的,而只是合规所须经历的必要手段。

又绕到哪去了,什么字符串函数,它不接受数值型参数哇!
在DBF文件中I型数据本来就是一个内码数据(字符串形式),取出来就是了,还要用什么函数的数值型参数!
这样看看:
CREATE TABLE c:\temp\tt (f1 I,f2 n(16))
INSERT INTO tt VALUES (-2147483648,123456789012346)
tt.dbf文件内容,图中红框框的 00 00 00 80 就是F1的-2147483648,直接取出 00 00 00 80 就是了。
只有本站会员才能查看附件,请 登录


#38
cssnet2023-03-14 16:43
以下是引用吹水佬在2023-3-14 16:22:27的发言:
在DBF文件中I型数据本来就是一个内码数据(字符串形式),取出来就是了,还要用什么函数的数值型参数!


你倒是有点儿将我绕糊涂啦。

我当然知道,I型数据在DBF中是以内码存放。
现在是打算在VFP程序代码中,以字符串类型来处理数值型变量值哇:

select MyTable
scan
    * 假设A1...A8都是I型数值字段:
    lcA1 = bintoc(A1)
    lcA1_A8 = bintoc(A1) + " " + bintoc(A2) + " " + bintoc(A3) + " " + bintoc(A4) + " " + bintoc(A5) + " " + bintoc(A6) + " " + bintoc(A7) + " " + bintoc(A8)
    * 简单统计一下,每一行中,A1出现的次数:   
    lnOccu = occu(lcA1, lcA1_A8)
    ? lnOccu
endscan

我有点不明白你的意思了:这样一个简单的“从数值到字符串”的转换,为什么企图借助低级文件处理函数,直接从DBF取出(你所表达的意思,可以这么理解吗?)?


[此贴子已经被作者于2023-3-14 16:48编辑过]

#39
吹水佬2023-03-14 16:50
回复 38楼 cssnet
给个实实在在的DBF测试好了,例举的也行。
#40
吹水佬2023-03-14 16:54
以下是引用cssnet在2023-3-14 16:43:19的发言:
我有点不明白你的意思了:这样一个简单的“从数值到字符串”的转换,为什么企图借助低级文件处理函数,直接从DBF取出(你所表达的意思,可以这么理解吗?)?

不要小看VFP,文件对于VFP来说,有时是不存在高低级别的,尤其是当作字符串处理。不是有STRTOFILE、FILETOSTR吗,这些不低级吧。
加上VFP高效的字符串处理能力,对于你这类问题还真不用USE操作字段。



[此贴子已经被作者于2023-3-14 16:56编辑过]

#41
吹水佬2023-03-14 18:06
以下是引用cssnet在2023-3-14 16:43:19的发言:
这样一个简单的“从数值到字符串”的转换

转换来转换去,相对不用转换直接读取就不是“简单的”了。
#42
cssnet2023-03-14 18:20
以下是引用吹水佬在2023-3-14 16:54:29的发言:
文件对于VFP来说,有时是不存在高低级别的


这话说得有些不太专业了。
你搜索一下VFP的帮助文件,王苏汉化版(曾广岷(TLDS_ZGM),王振鹏(RichardWZP),任明汉,王 苏(Wangsuww),都市夜猫(City Owl),……)
搜索关键词:
低级文件函数
#43
cssnet2023-03-14 18:33
以下是引用吹水佬在2023-3-14 16:54:29的发言:

不要小看VFP,……加上VFP高效的字符串处理能力


恰恰是看中了“VFP高效的字符串处理能力”,楼主这才会突发奇想,特意将数值型数据也转换为字符串,以便利用VFP的字符串函数,去处理一些简单的、无需数值参与计算的统计工作。
#44
吹水佬2023-03-14 18:42
以下是引用cssnet在2023-3-14 18:20:07的发言:

这话说得有些不太专业了。
你搜索一下VFP的帮助文件,王苏汉化版(曾广岷(TLDS_ZGM),王振鹏(RichardWZP),任明汉,王 苏(Wangsuww),都市夜猫(City Owl),……)
搜索关键词:
低级文件函数

VFP的低级文件函数通常是指F字头的Fxxx()函数,是通过文件句柄来操作文件。
VFP主要是与DBF文件打交道,涉及到低级文件函数也不多见。
再说,使用低级文件函数只是说从文件的底层来操作文件,这种操作并不一定是“低级”。
再再说,你的问题或者还真不用低级文件函数,也不用USE就可以直接从DBF中取出数据。
讲多无谓,给个实例,一试就清楚。

1